haskell - 什么是协变函子?
问题描述
我想了解,例如,为什么Maybe
类型是协变函子?
协变是什么意思?
请提供一个例子来澄清。
解决方案
协变函子只是普通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
的顺序相反:b
a
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 条件的函数x
。contramap
我们可以专攻Predicate
s:
contramap :: (a -> b) -> Predicate b -> Predicate a
这相当于:
contramap :: (a -> b) -> (b -> Bool) -> (a -> Bool)
基本上,给定 a Predicate
on b
s,以及从a
s到 b
s 的映射,您可以contramap
得到 a Predicate
on a
s。(我将把实现留作练习。)这是一个例子(未经测试):
hasMultChars :: Predicate String
hasMultChars = Predicate $ \x -> length x > 1
showInt :: Int -> String
showInt = show
intHasMultChars :: Predicate Int
intHasMultChars = contramap showInt hasMultChars
事实证明,与正常的协变函子相比,逆变函子不太常见,因此也没那么有用。所以在实践中,我们省略了“协变”,因为在大多数情况下它不会添加任何东西。
推荐阅读
- python - 尝试将简单的 ema 交叉策略从 PineScript 转换为 BackTrader .....结果不一样
- c# - Quickfixn:如何读取 SecurityList 并获取符号?
- c++ - 为什么标准库有一个模板<>?
- angular - 使用模拟器时,Firestore 规则中的 request.auth 为 null
- c# - 在 C# 中更新 SQL 数据表?
- sql - 无法通过查询从组中获取结果
- python - 如何按键合并制表符分隔的文件并向每个文件添加制表符?
- javascript - 如何删除“\\\”表单图像标签
- laravel - 使用 browsersync 时无法从移动设备访问 http://192.168.1.10:3000
- discord.js - 如何让不和谐机器人在任何频道中发送特定消息