Is there a Monad instance otherwise?

I just asked about it at the haskell-caf, but I suppose I can ask for it too. Is the next Monad instance for Backwards m valid?

 {-# Language RecursiveDo #-} import Control.Applicative.Backwards import Control.Monad.Fix instance MonadFix m => Monad (Backwards m) where m >>= f = Backwards $ do fin <- forwards (f int) int <- forwards m pure fin 

If so, can I also add this?

 instance MonadFix m => MonadFix (Backwards m) where mfix f = Backwards $ mfix (forwards . f) 
+7
haskell monads
source share
2 answers

No, that is not true; the laws of the monad are, at best, preserved in some approximate form. As Peter Pudlak’s answer shows, Backwards m >>= f doesn’t look very good when f is strict in its argument.

According to the laws of the monad,

 pure () >>= (\() -> m) = m 

But with this case, if I’m not mistaken,

 pure () >>= (\() -> m) = Backwards $ do fin <- forwards (int `seq` m) int <- pure () pure fin = Backwards $ fmap fst $ mfix $ \ ~(_, int) -> do fin <- forwards (int `seq` m) pure (fin, ()) 

If the main monad is "strict" (that is, its >>= strictly in the left operand), this will diverge.

+3
source share

For this, f must be lazy, i.e. the effect should not depend on the argument. docs say

mfix f performs action f only once, and the final output is returned as input. Therefore, f does not have to be strict, since then mfix f will diverge.

Buf if f in your case m >>= f will be strict, then the mfix block will be passed this mfix .

Consider a practical example where m - readLine >>= putStrLn . Reversing the order means "print data and then read." If the effect of the function beyond >>= is independent of the input, this diverges.

+2
source share

All Articles