I have come across the code below and thought I wanted to rewrite it in order to get a firmer grasp of the Monad. As I have tried to do below. It raises several questions about aspects that I apparently haven't understood fully.
type R = Int
type W = String
type S = Double
newtype RWSP a = RWSP {runRWSP :: R -> S ->
(a, W, S)}
instance Monad RWSP where
return a = RWSP(\_ state -> (a, mempty, state))
m >>= f = RWSP(\r state ->
let (a, w, state') = runRWSP m r state
(a', w', state'') = runRWSP (f a) r state'
in (a', w++w', state''))
instance Functor RWSP where
fmap = liftM
instance Applicative RWSP where
pure = return; (<*>) = ap
newtype CustomM a = CustomM {runCustomM :: a -> String}
instance Monad CustomM where
return a = CustomM (\a -> mempty)
m >>= f = CustomM (\a ->
let str = runCustomM m
str' = runCustomM (f a)
in (str' ++ str))
instance Functor CustomM where
fmap = liftM
instance Applicative CustomM where
pure = return; (<*>) = ap
1a. Why is the runRWSP needed in the original example after the let statement. Does this have to do with that a runRWSP takes a monad m, whereas the RWSP is a monad in itself with the type a which requires an anonymous function?
1b. In that case could one go about solving the original code by rewriting it so that no runRWSP was needed but rather a RWSP was used instead?
2a. What about the several nested tuples in the let expression. Why are both important. The f a seems to surround whatever the first runRWSP m r state returns and I guess we can only assume that this monad takes an r and an s due to its newtype definition, is that correctly? When I try to do something similar for the edited version I seem to get an error.
bc. Furthermore I suspect you can use the m
as an argument for runRWSP due to the reverse nature of newtype
like you would with: ghci> CharList "tdada" CharList {getCharList = "tdada"} ghci> getCharList (CharList "something") "something"
at http://learnyouahaskell.com/functors-applicative-functors-and-monoids#the-newtype-keyword
3a. Is it correct to say that the bind operator needs the runRWSP constructor on the right side, because the bind operator has as its output m b
which would require a function whereas the RWSP a
is a monad and not a function and therefore does not change the packed value a
to b
4a. How can I rewrite the monad correctly such that it will compile correctly with the new data type?