8

私の目標は、ReaderT WriterT スタックまたは RWS スタックのいずれかの内部でリスト モナドを使用する関数を作成することです。より一般的には、MonadReader、MonadWriter などの mtl 型クラス内で list モナドを使用するにはどうすればよいですか?

なぜ私はこれをやろうとしているのですか?この問題は、 Beginning Haskellの練習問題です。「ベースリストモナドをラップするMonadReaderとMonadWriterの両方の機能を使用するように求められます。関数が一般的であることを確認するには、2つの異なるモナドを使用して、要求された機能を[テスト]します。ReaderT r (WriterT w []) aRWST r w s m aしたがって、本はこれが可能であることを暗示しています。

リストモナドを使用するようにコンパイラに「指示」する方法がわかりません。2 レベル スタック ( ) または 3 レベル スタック ( ) のいずれかを使用するか、ask >>= lift両方を使用することはできませんが、両方を使用することはできません。ask >>= lift . liftRWST []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 回のリフトを試しましたが、成功しませんでした。askaを処理したいのですが[(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 では使用できません。したがって、これは私が探している解決策ではありません。

4

2 に答える 2