为什么 Haskell 中没有 `Cofunctor` 类型类?
Why there is no `Cofunctor` typeclass in Haskell?
Monads 从 Functor
类型 class 得到 fmap
。为什么 comonads 不需要 Cofunctor
class 中定义的 cofmap
方法?
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
不存在的原因。 "The dual concept of 'functor in general' is still 'functor in general'".
由于Functor
和Cofunctor
相同,monads和comonads都是使用Functor
定义的。但是不要因此而认为 monads 和 comonads 是一回事,它们不是。
一个 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
注意 "symmetry"。
还有一个就是逆变函子,定义为:
import Data.Functor.Contravariant
class Contravariant f where
contramap :: (b -> a) -> (f a -> f b)
供参考,
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
、<*>
和 join
。所以我们可以只关注 pure
+>>=
和 extract
+extend
。
我想您可能正在寻找类似
的东西
class InverseFunctor f where
unmap :: (f a -> f b) -> a -> b
由于 Monad
class 使得 "put things in" 变得容易,同时只允许对 "taking things out" 的一种假设方法,而 Comonad
做了一些相反的事情为此,您的要求最初听起来很明智。然而,>>=
和 extend
之间存在显着的不对称,这将阻碍任何定义 unmap
的尝试。请特别注意 >>=
的第一个参数的类型为 m a
。 extend
的第二个参数的类型为 w a
—not a
.
实际上,你错了:有一个!
Monads 从 Functor
类型 class 得到 fmap
。为什么 comonads 不需要 Cofunctor
class 中定义的 cofmap
方法?
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
不存在的原因。 "The dual concept of 'functor in general' is still 'functor in general'".
由于Functor
和Cofunctor
相同,monads和comonads都是使用Functor
定义的。但是不要因此而认为 monads 和 comonads 是一回事,它们不是。
一个 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
注意 "symmetry"。
还有一个就是逆变函子,定义为:
import Data.Functor.Contravariant
class Contravariant f where
contramap :: (b -> a) -> (f a -> f b)
供参考,
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
、<*>
和 join
。所以我们可以只关注 pure
+>>=
和 extract
+extend
。
我想您可能正在寻找类似
的东西class InverseFunctor f where
unmap :: (f a -> f b) -> a -> b
由于 Monad
class 使得 "put things in" 变得容易,同时只允许对 "taking things out" 的一种假设方法,而 Comonad
做了一些相反的事情为此,您的要求最初听起来很明智。然而,>>=
和 extend
之间存在显着的不对称,这将阻碍任何定义 unmap
的尝试。请特别注意 >>=
的第一个参数的类型为 m a
。 extend
的第二个参数的类型为 w a
—not a
.
实际上,你错了:有一个!