2017-01-24 3 views
2

Iましhereから取られた以下のコード、:私は)data Blog areaderTの正確な役割をSQLiteでReaderTとrunReaderTを使用していますか?

1を理解しようとしている

type Blog a = ReaderT SQLiteHandle IO a 
data BlogDBException = BlogDBException String deriving (Show, Typeable) 
instance Exception BlogDBException 

run :: Blog a -> IO a 
run m = do 
    db <- openConnection "myblog.db" 
    runReaderT m db --runReaderT :: ReaderT r m a -> (r -> m a) 


sql :: String -> Blog (Either String[[Row Value]]) 
sql query = do 
    db <- ask --ask :: Monad m => ReaderT r m r 
    liftIO $ do 
    putStrLn query 
    execStatement db query 


dbQuery :: Blog [Int] 
dbQuery = do 
    r <- sql "select UID from UIDS;" 
    case r of 
    Right [rows] -> return [fromIntegral uid | [(_, Int uid)] <- rows] 
    Left s -> liftIO $ throwIO (BlogDBException s) 
    _ -> liftIO $ throwIO (BlogDBException "Invalid result") 

2)ここではrunReaderTとは何ですか?

3)askの機能はどのように機能しますか?

誰でも簡単な説明がありますか?これは初めてReaderモナドで作業しています。

答えて

2

1)この例では、ReaderTの目的は、各ファンクションに追加のパラメータを追加せずに、タイプがSQLiteHandleの値を使用できるようにすることです。

2)runReaderTReaderTnewtype ReaderT r m a = ReaderT { runReaderT :: r -> m a}を「アンラップ」します。表示されているとおり、実際の表示はr -> m aです。rの提供アイテムからm aへの関数で、直接扱っていたと考えています。したがって、ReaderTは、新しいパラメータを関数に追加する必要があるという事実を避けているわけではありません。それはあなたのためにそれを隠しているだけです。

3)runReaderT ask == runReaderT $ ReaderT return == return == r -> m rしたがって、askは、「環境」r(追加のパラメータ)へのアクセスを、単純に基になるモナドにラッピングすることで提供しています。

非常に単純な(実際にはあまりにも単純すぎる)例です。私はHaskellのを学び始めたとき

type ModeFlag = Int 

g :: ModeFlag -> IO() 
g modeFlag = ... -- take some action based on modeFlag 

h :: ReaderT ModeFlag IO() 
h = do 
    modeFlag <- ask 
    ... -- take some action based on modeFlag 

に相当し、この手法の有用性は、私にはすぐに明らかではなかったです。ただし、構成パラメータが多数ある場合や、すぐに構成パラメータを追加する必要がある場合があります。関数に新しい引数を追加することは非常に不便です。代わりに、設定値をレコードにパックし、ReaderT経由でアプリケーション全体に渡してください。 askのようなasksという機能がありますが、rの値に適用する機能もあります。これは、レコードから特定のフィールドを抽出するために使用できます。

data Config :: Config { param1 :: Int, param2 :: String, ... other fields } 

doStuff :: ReaderT Config IO() 
doStuff = do 
    i <- asks param1 
    s <- asks param2 
    undefined -- do some stuff 

かなりクールですが、私はあまり使用していないlocal機能を含む(下部のhttp://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Reader.html)ドキュメントのReaderReaderTのいくつかのより多くの例があります。

関連する問題