首页 > 解决方案 > 什么是协变函子?

问题描述

我想了解,例如,为什么Maybe类型是协变函子?

协变是什么意思?

请提供一个例子来澄清。

标签: haskell

解决方案


协变函子只是普通Functor类:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

例如,Maybe(如您所述):

instance Functor Maybe where
    fmap _ Nothing = Nothing
    fmap f (Just a) = Just (f a)

但是,还有另一种类型的函子:逆变函子。这些定义如下:

class Contravariant f where
    contramap :: (a -> b) -> f b -> f a

请注意,与 相比fmap,与contramap的顺序相反:ba

fmap      ::       Functor f => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a
                                         --   ^      ^
                                         --   look!

现在,这个疯狂Contravariant的班级甚至有任何实例吗?嗯,是。例如,这是 a 的定义Predicate

newtype Predicate x = Predicate { decide :: x -> Bool }

换句话说, aPredicate x是一个计算 a 条件的函数xcontramap我们可以专攻Predicates:

contramap :: (a -> b) -> Predicate b -> Predicate a

这相当于:

contramap :: (a -> b) -> (b -> Bool) -> (a -> Bool)

基本上,给定 a Predicateon bs,以及从as bs 的映射,您可以contramap得到 a Predicateon as。(我将把实现留作练习。)这是一个例子(未经测试):

hasMultChars :: Predicate String
hasMultChars = Predicate $ \x -> length x > 1

showInt :: Int -> String
showInt = show

intHasMultChars :: Predicate Int
intHasMultChars = contramap showInt hasMultChars

事实证明,与正常的协变函子相比,逆变函子不太常见,因此也没那么有用。所以在实践中,我们省略了“协变”,因为在大多数情况下它不会添加任何东西。


推荐阅读