为什么 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'".

由于FunctorCofunctor相同,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

请注意,给定 extractextend 你可以产生 fmapduplicate,并且给定 return>>= 你可以产生 fmappure<*>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 aextend 的第二个参数的类型为 w anot a.

实际上,你错了:有一个!

https://hackage.haskell.org/package/acme-cofunctor