Monads从fmap
类型类获得Functor
。为什么comonads不需要cofmap
类中定义的Cofunctor
方法?
答案 0 :(得分:21)
Functor
定义为:
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
Cofunctor
可以定义如下:
class Cofunctor f where
cofmap :: (b -> a) -> (f b -> f a)
因此,两者在技术上是相同的,这就是Cofunctor
不存在的原因。 "'仿函数的双重概念'仍然是一般的算符'"。
由于Functor
和Cofunctor
相同,因此使用Functor
定义monad和comonad。但是,不要让它让你认为monad和comonad是同一个东西,他们不是。
monad被定义(简化)为:
class Functor m => Monad where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
comonad(再次简化)是否:
class Functor w => Comonad where
extract :: w a -> a
extend :: (w a -> b) -> w a -> w b
注意"对称性"。
另一件事是逆变函子,定义为:
import Data.Functor.Contravariant
class Contravariant f where
contramap :: (b -> a) -> (f a -> f b)
答案 1 :(得分:5)
实际上,你错了:有一个!
答案 2 :(得分:4)
供参考,
class Functor w => Comonad w where
extract :: w a -> a
duplicate :: w a -> w (w a)
extend :: (w a -> b) -> w a -> w b
instance Applicative m => Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
join :: Monad m => m (m a) -> m a
请注意,给定extract
和extend
,您可以生成fmap
和duplicate
,并且return
和>>=
可以生成fmap
和pure
{1}},<*>
,join
和pure
。因此,我们只关注>>=
+ extract
和extend
+ class InverseFunctor f where
unmap :: (f a -> f b) -> a -> b
。
我想你可能正在寻找像
这样的东西Monad
由于Comonad
类使得“放入内容”变得容易,而只允许某种假设性方法来“解决问题”,并且>>=
做了与此相反的事情,因此您的请求最初听起来很明智。但是,extend
和unmap
之间存在显着的不对称性,这会阻碍任何定义>>=
的尝试。请特别注意m a
的第一个参数的类型为extend
。 w a
的第二个参数类型为a
- 不是 GET
。