在 monad 实例声明中使用 monad 超类?
Use of a monad superclass in a monad instance declaration?
我正在使用以下数据类型实现一个非常简单的穷人并发结构:
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 = Done
Q1。我说 Atomic $ (liftM (>>= f) m)
正在创建一个新的 Atomic
monad 是否正确,其中包含应用于 m
内部值的 f
(* -> *
) 的结果?
Q2。我说这里使用 superclass Monad m
来启用 liftM
是否正确?如果是这样,因为这是 Monad
class 的一个实例,为什么不能直接访问 liftM
?
Q1。它正在创造 Atomic
价值 。 Monad 是类型级别的映射。由于 f
是 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
统一。当您从 Atomic
中提取值 m
并将其传递给 liftM
时,您使用 monad m
的绑定(通过 liftM
)来提取内部 C m a
传递给 f
。 liftM
定义的第二部分将结果重新包装为 m (C m b)
,您将其包装在 Atomic
中。所以是的。
Q2。是的。但它是底层 monad m
的 liftM
。 C m a
的 liftM
是根据实例定义的(它的 >>=
和 return
)。通过使用 C m a
的 liftM
(如果您设法根据 liftM
定义 >>=
),您将得到一个循环定义。您需要约束 Monad m
来为 m (C m a)
创建管道以穿过 >>=
和 f
。事实上,正如 Benjamin Hodgson 所指出的,Monad m
是一个不必要的强约束,Functor m
就足够了。 C
实际上是 Free
together with the relevant implementations 这一事实提供了对此事最深入的了解。
我正在使用以下数据类型实现一个非常简单的穷人并发结构:
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 = Done
Q1。我说 Atomic $ (liftM (>>= f) m)
正在创建一个新的 Atomic
monad 是否正确,其中包含应用于 m
内部值的 f
(* -> *
) 的结果?
Q2。我说这里使用 superclass Monad m
来启用 liftM
是否正确?如果是这样,因为这是 Monad
class 的一个实例,为什么不能直接访问 liftM
?
Q1。它正在创造 Atomic
价值 。 Monad 是类型级别的映射。由于 f
是 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
统一。当您从 Atomic
中提取值 m
并将其传递给 liftM
时,您使用 monad m
的绑定(通过 liftM
)来提取内部 C m a
传递给 f
。 liftM
定义的第二部分将结果重新包装为 m (C m b)
,您将其包装在 Atomic
中。所以是的。
Q2。是的。但它是底层 monad m
的 liftM
。 C m a
的 liftM
是根据实例定义的(它的 >>=
和 return
)。通过使用 C m a
的 liftM
(如果您设法根据 liftM
定义 >>=
),您将得到一个循环定义。您需要约束 Monad m
来为 m (C m a)
创建管道以穿过 >>=
和 f
。事实上,正如 Benjamin Hodgson 所指出的,Monad m
是一个不必要的强约束,Functor m
就足够了。 C
实际上是 Free
together with the relevant implementations 这一事实提供了对此事最深入的了解。