My goal is to create a function that uses the list monad in the ReaderT WriterT stack or the RWS stack. More generally, how to use the monad list inside mtl typeclasses like MonadReader, MonadWriter?
Why am I trying to do this? This issue is an exercise in Haskell Start . He asks me to "use the functions of both MonadReader and MonadWriter, wrapping the monad of the base list. To verify that the function is shared, use two different monads to [verify] the requested functionality: ReaderT r (WriterT w []) a and RWST rwsma " Therefore, the book implies this is possible.
I can't figure out how to tell the compiler to use a list monad. If I use ask >>= lift or ask >>= lift . lift ask >>= lift . lift , I can get either a level 2 stack ( RWST [] ) or 3 stack levels ( ReaderT WriterT [] ), but not both.
At the center of my question:
pathImplicitStack' start end | start == end = tell [end] pathImplicitStack' start end = do (s0, e0) <- ask >>= lift guard $ s0 == start tell [start] pathImplicitStack' e0 end
In addition, I would like to know how to enter a function. My best attempt so far looks something like pathImplicitStack' :: (MonadReader [(Int, Int)] m, MonadWriter [Int] m, MonadPlus m) => Int -> Int -> m () I know this is wrong perhaps the list monad is missing. Also, I think MonadPlus might be useful in a type signature, but I'm not quite sure.
This line: do (s0, e0) <- ask >>= lift is something that is not pleasant to me. I tried 0, 1 and 2 elevators without success. I would like to ask for [(Int, Int)] , and then use the list monad to process just (Int, Int) (and let the list monad try all the possibilities for me).
As part of the exercise, I need to be able to call pathImplicitStack' with both of these functions (or very similar functions):
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 ()
This is related to my previous question: How to use list monad inside ReaderT?
Entire file for easy testing:
{-# 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
change
Based on the image of John L, I tried
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
but, as he noted, it can only be used with one monad transformer to wrap the list monad, i.e. RSWT, and cannot be used with ReaderT WriterT. So this is not the solution I'm looking for.