大多数 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为什么是
MPlusNonDetEff Bool而不是NonDetEff a a?除了使用CoYoneda 函子之外,有没有办法让它与Free我们需要数据类型成为函子一起工作?- 因为
forkExec我根本不知道如何进行。