我正在用以下数据类型实现一个非常简单的穷人并发结构:
data C m a = Atomic (m (C m a)) | Done a我正在为此创建一个monad实例:
instance Monad m => Monad (C m) where
(>>=) (Atomic m) f = Atomic $ (liftM (>>= f) m)
(>>=) (Done v) f = f v
return = DoneQ1。我说得对吗?Atomic $ (liftM (>>= f) m)正在创建一个新的Atomic monad,其中包含应用于m内部的值的f (* -> *)的结果。
Q2。我说得对吗,在这里使用超类Monad m来启用liftM?如果是这样的话,既然这是Monad类的一个实例,为什么不能直接访问liftM?
发布于 2017-03-16 10:24:57
Q1。它正在创建Atomic value。Monad是类型级别的映射。因为f是>>= of C m a的第二个参数,所以我们知道它的类型。
f :: Monad m => a -> C m b因此
(>>= f) :: Monad m => C m a -> C m b是否扩展f以打开其参数,以及
liftM (>>= f) :: (Monad m1, Monad m) => m1 (C m a) -> m1 (C m b)只需将转换提升到m1,在您的设置中,该转换将与m统一。当您从m提取值Atomic并将其传递给liftM时,您可以使用monad m的绑定(通过liftM)提取要传递给f的内部C m a。liftM定义的第二部分将结果重新包装为一个m (C m b),您将其包装在Atomic中。
Q2。是。但它是底层单一市场( monad m )的一个m。liftM for C m a是根据实例( >>=和return)定义的。通过使用C m a的liftM (如果您设法从liftM的角度定义>>= ),您将得到一个循环定义。您需要约束Monad m来创建m (C m a)穿越>>=和f的管道。事实上,正如本杰明·霍奇森指出的那样,Monad m是一个不必要的强约束,Functor m就足够了。C实际上是C 39以及相关的C40给出了最深入的见解。
https://stackoverflow.com/questions/42830035
复制相似问题