首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是协变函子?

什么是协变函子?
EN

Stack Overflow用户
提问于 2019-03-19 07:17:42
回答 2查看 943关注 0票数 8

我想要理解,为什么Maybe类型是一个协变函子?

协变是什么意思?

请举例说明。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-19 07:44:38

协变函子只是普通的Functor类:

代码语言:javascript
复制
class Functor f where
    fmap :: (a -> b) -> f a -> f b

例如,Maybe (正如您所提到的):

代码语言:javascript
复制
instance Functor Maybe where
    fmap _ Nothing = Nothing
    fmap f (Just a) = Just (f a)

然而,还有另一种函子:反变体函子。它们的定义如下:

代码语言:javascript
复制
class Contravariant f where
    contramap :: (a -> b) -> f b -> f a

请注意,与fmap相比,contramap颠倒了ba的顺序。

代码语言:javascript
复制
fmap      ::       Functor f => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a
                                         --   ^      ^
                                         --   look!

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

代码语言:javascript
复制
newtype Predicate x = Predicate { decide :: x -> Bool }

换句话说,Predicate x是计算x上的条件的函数。我们可以专门从contramapPredicate的:

代码语言:javascript
复制
contramap :: (a -> b) -> Predicate b -> Predicate a

相当于:

代码语言:javascript
复制
contramap :: (a -> b) -> (b -> Bool) -> (a -> Bool)

基本上,给定一个Predicate on b,以及一个从ab的映射,您可以contramap来获得a上的Predicate。(我将把实现作为一个练习。)下面是一个示例(未经测试):

代码语言:javascript
复制
hasMultChars :: Predicate String
hasMultChars = Predicate $ \x -> length x > 1

showInt :: Int -> String
showInt = show

intHasMultChars :: Predicate Int
intHasMultChars = contramap showInt hasMultChars

事实证明,与普通的协变函子相比,反变函子不那么常见--也就没那么有用了。所以在实践中,我们忽略了“协变”,因为它在大多数情况下并没有增加任何东西。

票数 16
EN

Stack Overflow用户

发布于 2019-03-19 07:44:27

协变函子是指“内”和“外”箭头指向同一方向的函子。

代码语言:javascript
复制
class Functor f where
  fmap :: (a -> b) -> (f a -> f b)

反变函子是指“内”和“外”箭头指向相反方向的函子。

代码语言:javascript
复制
class Contravariant f where
  contramap :: (a -> b) -> (f a <- f b)

...or,使用适当的Haskell语法,

代码语言:javascript
复制
  contramap :: (a -> b) -> (f b -> f a)

这通常表示参数类型作为数据类型中的函数参数出现在某个地方,如

代码语言:javascript
复制
data DepInt x = DepInt (x -> Int)

instance Contravariant DepInt where
  contramap f (DepInt g) = DepInt $ g . f

相反,如果该参数只显示为- is或函数箭头的右边,则它是一个协变函子。这是大多数函子的情况,这就是为什么这个类被简单地称为Functor

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55235467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档