我刚刚在haskell-cafe上问过这个问题,但我想我也可以在这里问一下。 Backwards m
的以下Monad
实例是否有效?
{-# 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
如果是这样,我还可以添加吗?
instance MonadFix m => MonadFix (Backwards m) where
mfix f = Backwards $ mfix (forwards . f)
答案 0 :(得分:3)
不,它无效; monad法则充其量只能以某种近似的方式持有。正如Petr Pudlák's answer所示,当http://username:password@myserver.com/api.php
在其参数中严格时,Backwards m >>= f
表现不佳。
根据monad法律,
f
但是有了这个例子,如果我没有弄错的话,
pure () >>= (\() -> m) = m
如果潜在的monad是&#34; strict&#34; (即,它的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, ())
在左操作数上是严格的),这将会发散。
答案 1 :(得分:2)
对于这个f
需要是懒惰的,也就是说,效果不能取决于参数。 docs说
mfix f
仅执行一次动作f
,最终输出作为输入反馈。因此f
不应该严格,因为mfix f
会分歧。
如果您的案例f
中的m >>= f
严格,那么Buf会传递给mfix
。
让我们考虑m
为readLine >>= putStrLn
的实际示例。颠倒顺序意味着“打印数据,然后读取它”。除非>>=
后面的函数的效果不依赖于输入,否则这会有所不同。