Newbie question. I can't believe I'm still struggling to grapple MTL stuff. The lucid library has HtmlT m a which has a MonadState instance. But how exactly do you use it? I tried flip runState mempty someFunc where someFunc is MonadState String m => HtmlT m () but that doesn't compile.
Hi, I have an issue with monad transformer.
Here is the code that I wrote
collectRendu :: [String] -> IO [Rendu]
collectRendu candidate_subdir_names =
do
dirs <- listDirectory rootDirectory
catMaybes <$> mapM aux dirs
where
aux:: FilePath -> IO (Maybe Rendu)
aux dir = do
candidate <- headMaybe <$> filterM (doesRenduExists dir) candidate_subdir_names
case candidate of Nothing -> return Nothing
Just x -> Just <$> appendNewRendu dir x
doesRenduExists studentNamedDir = doesDirectoryExist . ((rootDirectory </> studentNamedDir) </>)
the part that doesn't please me is the "case candidate of...".
Candidate type is "Maybe Filepath", I want to return a "IO (Maybe Rendu)", and type of appendNewRendu is "FilePath -> FilePath -> IO Rendu".
I first used fmap until I realised that "(appendNewRendu dir) <$> candidate" will yield me a "Maybe (IO Rendu)".
I suspect there is a better way, but I'm a bit stuck. Since IO and Maybe are stacked monad I suspect there is something to do with monad transformers, but I didn't used them that much.
Don't bother with transformers just to remove a little bit of boilerplate in single function, I don't think it's worth it from readability perspective
In this case, you can simply use traverse:
which means that it doesn't fit m String for some m containing MaybeT
You're basically making use of fact that internal implementation of MaybeT uses Maybe - it could just as well use something different, and so compiler has no reason to coerce it into MaybeT by itself
Newbie question. I can't believe I'm still struggling to grapple MTL stuff. The lucid library has
HtmlT m a
which has a MonadState instance. But how exactly do you use it? I triedflip runState mempty someFunc
where someFunc isMonadState String m => HtmlT m ()
but that doesn't compile.StateT String (HtmlT Identity) ()
seems one step forward, but then you have tolift
all UI elements, thus losing access to state.Aha,
flip runStateT mempty $ evalHtmlT someFunc
works.Grr, but that doesn't render the Html at runtime
Okay, after reading the source ... unpack and pack it back:
HtmlT $ fmap fst $ flip runStateT mempty $ runHtmlT someFunc
you're doing something cray here!
monad transformers should only need to be unpeeled in
main
flip runState myState $ runHtmlT myHTMLFUNCTION
the
State
here is globalif you want local state semantic, you want to build a
StateT s Html
insteadWith
StateT s Html
you would havelift
when rendering UI, but at that point - access to state is lost.And it seems that the lucid library recommends putting State inside the HtmlT transformer: https://hackage.haskell.org/package/lucid-2.9.12/docs/Lucid.html#t:HtmlT
So to "inject" an inner monad, I had to peel the skin, apply the topical cream (runState), then put it back.
(well, that reads pretty gory)
Real-world code that lead to all this: https://funprog.zulipchat.com/#narrow/stream/201385-Haskell/topic/HTML.20in.20Haskell/near/188742480
Hi, I have an issue with monad transformer.
Here is the code that I wrote
the part that doesn't please me is the "case candidate of...".
Candidate type is "Maybe Filepath", I want to return a "IO (Maybe Rendu)", and type of appendNewRendu is "FilePath -> FilePath -> IO Rendu".
I first used fmap until I realised that "(appendNewRendu dir) <$> candidate" will yield me a "Maybe (IO Rendu)".
I suspect there is a better way, but I'm a bit stuck. Since IO and Maybe are stacked monad I suspect there is something to do with monad transformers, but I didn't used them that much.
Asking for "(a -> m b) -> Maybe a -> m Maybe b" on Hoogle didn't yield any result
ho nvm if I correctly put parenthesis it works
Don't bother with transformers just to remove a little bit of boilerplate in single function, I don't think it's worth it from readability perspective
In this case, you can simply use
traverse
:thanks
it also looks like mapM works here
traverse and mapM are the same ?
Yeah, because of laws
mapM
is more of a legacy thingok
out of curiosity there is a way to use
lift
that would work here ? I very rarely use monad transformers and still lack the intuitionThere's
MaybeT
:which would probably work something like this:
thanks
MaybeT is not "automatic" by default ?
I mean I never need to add ReaderT or WriterT or StateT
You mean
MaybeT
constructor in example above?yes
well,
which means that it doesn't fit
m String
for somem
containingMaybeT
You're basically making use of fact that internal implementation of
MaybeT
usesMaybe
- it could just as well use something different, and so compiler has no reason to coerce it intoMaybeT
by itselfit just seems automatic because you're usually using more complex combinators for
Reader
etcask === ReaderT pure
yes that's right