私の目標は、ReaderT WriterT スタックまたは RWS スタックのいずれかの内部でリスト モナドを使用する関数を作成することです。より一般的には、MonadReader、MonadWriter などの mtl 型クラス内で list モナドを使用するにはどうすればよいですか?
なぜ私はこれをやろうとしているのですか?この問題は、 Beginning Haskellの練習問題です。「ベースリストモナドをラップするMonadReaderとMonadWriterの両方の機能を使用するように求められます。関数が一般的であることを確認するには、2つの異なるモナドを使用して、要求された機能を[テスト]します。ReaderT r (WriterT w []) a
」RWST r w s m a
したがって、本はこれが可能であることを暗示しています。
リストモナドを使用するようにコンパイラに「指示」する方法がわかりません。2 レベル スタック ( ) または 3 レベル スタック ( ) のいずれかを使用するか、ask >>= lift
両方を使用することはできませんが、両方を使用することはできません。ask >>= lift . lift
RWST []
ReaderT WriterT []
私の質問の焦点:
pathImplicitStack' start end | start == end = tell [end]
pathImplicitStack' start end =
do (s0, e0) <- ask >>= lift
guard $ s0 == start
tell [start]
pathImplicitStack' e0 end
さらに、関数の入力方法を知りたいです。pathImplicitStack' :: (MonadReader [(Int, Int)] m, MonadWriter [Int] m, MonadPlus m) => Int -> Int -> m ()
これまでの私の最善の試みは、これが正しくないことを知っているように見えます。リストモナドがおそらく欠落しています。また、MonadPlus は型シグネチャに役立つ可能性があると思いますが、よくわかりません。
この行:do (s0, e0) <- ask >>= lift
私に問題を引き起こしているものです。0、1、および 2 回のリフトを試しましたが、成功しませんでした。ask
aを処理したいのですが[(Int, Int)]
、リスト モナドを使用して a だけを処理します(Int, Int)
(そして、リスト モナドにすべての可能性を試してもらいます)。
演習の一環として、pathImplicitStack'
これらの関数 (または非常に類似した関数) の両方を呼び出すことができる必要があります。
pathImplicitRW :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRW edges start end = execWriterT rdr
where rdr = runReaderT (pathImplicitStack' start end) edges :: WriterT [Int] [] ()
pathImplicitRWS :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRWS edges start end = map snd exec
where exec = execRWST (pathImplicitStack' start end) edges ()
これは、以前の質問に関連しています: ReaderT 内でリスト モナドを使用するにはどうすればよいですか?
簡単にテストするためのファイル全体:
{-# LANGUAGE FlexibleContexts #-}
module Foo where
import Control.Monad.Reader
import Control.Monad.Writer
import Control.Monad.RWS
graph1 :: [(Int, Int)]
graph1 = [(2013,501),(2013,1004),(501,2558),(1004,2558)]
pathImplicitRW :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRW edges start end = execWriterT rdr
where rdr = runReaderT (pathImplicitStack' start end) edges :: WriterT [Int] [] ()
pathImplicitRWS :: [(Int, Int)] -> Int -> Int -> [[Int]]
pathImplicitRWS edges start end = map snd exec
where exec = execRWST (pathImplicitStack' start end) edges ()
pathImplicitStack' :: (MonadReader [(Int, Int)] m, MonadWriter [Int] m, MonadPlus m) => Int -> Int -> [m ()]
pathImplicitStack' start end | start == end = tell [end]
pathImplicitStack' start end =
do (s0, e0) <- ask >>= lift
guard $ s0 == start
tell [start]
pathImplicitStack' e0 end
編集
私が試したJohn Lのフィードバックに基づいて
pathImplicitStack' :: (MonadReader [(Int, Int)] (t []), MonadWriter [Int] (t []), MonadPlus (t []), MonadTrans t) => Int -> Int -> t [] ()
pathImplicitStack' start end | start == end = tell [end]
pathImplicitStack' start end =
do (s0, e0) <- ask >>= lift
guard $ s0 == start
tell [start]
pathImplicitStack' e0 end
しかし、彼が指摘したように、それはリストモナドをラップするために 1 つのモナド変換子、つまり RSWT でのみ使用でき、ReaderT WriterT では使用できません。したがって、これは私が探している解決策ではありません。