大多数 monadic 函数采用纯参数并返回一个 monadic 值。但是有一些也需要单子参数,例如:
mplus :: (MonadPlus m) => m a -> m a -> m a
finally :: IO a -> IO b -> IO a
forkIO :: m () -> m ThreadId
-- | From Control.Monad.Parallel
forkExec :: m a -> m (m a)
他们每个人似乎都提出了一个不同的问题,我无法掌握如何使用自由单子对这些动作进行编码的通用方法。
在两者中
finally
,forkIO
问题在于一元参数的类型与结果不同。但是免费的人需要它们是相同的类型,因为IO a
被编码类型的类型变量替换,比如data MyFunctor x = Finally x x x
,它只会 encodeIO a -> IO a -> IO a
。在33 行 Haskell 代码中从零到协作线程作者
Fork next next
用来拳头实现cFork :: (Monad m) => Thread m Bool cFork = liftF (Fork False True)
然后用它来实现
fork :: (Monad m) => Thread m a -> Thread m ()
其中输入和输出具有不同的类型。但我不明白这是使用某些过程得出的,还是只是一个适用于这个特定目的的临时想法。
mplus
特别令人困惑:天真的编码为data F b = MZero | MPlus b b
分布
>>=
,建议更好的实现更复杂。并且从 free 中删除了 free 的本机MonadPlus
实现。在更自由的情况下,它是通过添加来实现的
data NonDetEff a where MZero :: NonDetEff a MPlus :: NonDetEff Bool
为什么是
MPlus
NonDetEff Bool
而不是NonDetEff a a
?除了使用CoYoneda 函子之外,有没有办法让它与Free
我们需要数据类型成为函子一起工作?- 因为
forkExec
我根本不知道如何进行。