contravariant 模块

contravariant 模块需要安装

$ cabal install contravariant
contravariant-1.4
Prelude> :m +Data.Functor.Contravariant
Prelude Data.Functor.Contravariant>

Contravariant Functor(逆变函子)

class Contravariant f where
contramap :: (a -> b) -> f b -> f a (>$) :: b -> f b -> f a
(>$) = contramap . const

Functor(函子)类型类是协变的,因此它可以被看做 Covariant Functor (协变函子)的简写。

Functor是协变,是因为它改变的是输出端,相对于函数定义来说是正向的(positive)。

与此相对,Contravariant 类型类是逆变的,它是 Contravariant Functor (逆变函子)的简写。

Contravariant是逆变,是因为它改变的是输入端,相对于函数定义来说是反向的(negative)。

Contravariant 的法则

1. contramap id = id
2. contramap f . contramap g = contramap (g . f)

Predicate(谓词)是个Contravariant

newtype Predicate a = Predicate { getPredicate :: a -> Bool }

instance Contravariant Predicate where
contramap f g = Predicate $ getPredicate g . f

Predicate(谓词 )类型封装了一个 a -> Bool 类型的函数。

证明 Predicate 符合 Contravariant 的法则
1. contramap id = id
contramap id p
= Predicate $ getPredicate p . id
= Predicate $ getPredicate p
= p = id p
2. contramap f . contramap g = contramap (g . f)
(contramap f . contramap g) p
= contramap f (contramap g p)
= contramap f (Predicate $ getPredicate p . g)
= Predicate $ getPredicate (Predicate $ getPredicate p . g) . f
= Predicate $ (getPredicate p . g) . f
= Predicate $ getPredicate p . g . f
contramap (g . f) p
= Predicate $ getPredicate p . (g . f)
= Predicate $ getPredicate p . g . f
import Data.Functor.Contravariant

greaterThanThree :: Predicate Int
greaterThanThree = Predicate (> 3) lengthGTThree :: Predicate [a]
lengthGTThree = contramap length greaterThanThree englishGTThree :: Predicate Int
englishGTThree = contramap english lengthGTThree english :: Int -> String
english 1 = "one"
english 2 = "two"
english 3 = "three"
english 4 = "four"
english 5 = "five"
english 6 = "six"
english 7 = "seven"
english 8 = "eight"
english 9 = "nine"
english 10 = "ten" main :: IO ()
main = print $ filter (getPredicate englishGTThree) [1..10] -- [3,4,5,7,8,9]

Comparison a 是个Contravariant

newtype Comparison a = Comparison { getComparison :: a -> a -> Ordering }

instance Contravariant Comparison where
contramap f g = Comparison $ on (getComparison g) f

Comparison a(同类比较)类型封装了一个 a -> a -> Ordering 类型的函数(比如 compare 函数)。

on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(*) `on` f = \x y -> f x * f y 证明 Comparison a 符合 Contravariant 的法则
1. contramap id = id
contramap id c
= Comparison $ on (getComparison c) id
= Comparison $ \x y -> (getComparison c) (id x) (id y)
= Comparison $ \x y -> (getComparison c) x y
= Comparison $ getComparison c
= c = id c
2. contramap f . contramap g = contramap (g . f)
(contramap f . contramap g) c
= contramap f (contramap g c)
= contramap f (Comparison $ on (getComparison c) g)
= contramap f (Comparison $ on (getComparison c) g)
= Comparison $ on (getComparison (Comparison $ on (getComparison c) g)) f
= Comparison $ on (on (getComparison c) g) f
= Comparison $ on (\x y -> (getComparison c) (g x) (g y)) f
= Comparison $ \x y -> (\x y -> (getComparison c) (g x) (g y)) (f x) (f y)
= Comparison $ \x y -> (getComparison c) (g (f x)) (g (f y))
contramap (g . f) c
= Comparison $ on (getPredicate c) (g . f)
= Comparison $ \x y (getPredicate c) ((g . f) x) ((g . f) y)
= Comparison $ \x y -> (getComparison c) (g (f x)) (g (f y))
Prelude Data.Functor.Contravariant Data.List> sortBy (getComparison $ contramap length $ Comparison compare) ["Groovy","Java","Scala"]
["Java","Scala","Groovy"]
Prelude Data.List Data.Function> sortBy (compare `on` length) ["Groovy","Java","Scala"]
["Java","Scala","Groovy"]
Prelude Data.List> sortOn length ["Groovy","Java","Scala"]
["Java","Scala","Groovy"]

Const a 是个Contravariant

newtype Const a b = Const { getConst :: a }

instance Contravariant (Const a) where
contramap _ (Const a) = Const a

Const a b 封装了一个值 a。

证明 Const a 符合 Contravariant 的法则
1. contramap id = id
contramap id (Const a) = Const a = id (Const a)
2. contramap f . contramap g = contramap (g . f)
(contramap f . contramap g) (Const a)
= contramap f (contramap g (Const a))
= contramap f (Const a)
= Const a
= contramap (g . f) (Const a)

正向与反向

a  -- positive position
a -> Bool -- negative position
(a -> Bool) -> Bool -- positive position
((a -> Bool) -> Bool) -> Bool -- negative position
a -> Bool -> Bool = a -> (Bool -> Bool) -- negative position

参考链接

What is a contravariant functor?

Haskell语言学习笔记(35)Contravariant的更多相关文章

  1. Haskell语言学习笔记(88)语言扩展(1)

    ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...

  2. Haskell语言学习笔记(79)lambda演算

    lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...

  3. Haskell语言学习笔记(69)Yesod

    Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...

  4. Haskell语言学习笔记(20)IORef, STRef

    IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...

  5. Haskell语言学习笔记(39)Category

    Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...

  6. Haskell语言学习笔记(72)Free Monad

    安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...

  7. Haskell语言学习笔记(44)Lens(2)

    自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...

  8. Haskell语言学习笔记(38)Lens(1)

    Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...

  9. Haskell语言学习笔记(92)HXT

    HXT The Haskell XML Toolbox (hxt) 是一个解析 XML 的库. $ cabal install hxt Installed hxt-9.3.1.16 Prelude&g ...

随机推荐

  1. 淘宝 code 使用

    淘宝 code上 svn 使用,基本流程: 新建项目 mkdir 创建 branches 文件夹(新建项目的时候,只有 trunk) copy 来创建新分支 checkout 主干和(或)分支到本地 ...

  2. JMeter和JMeterPlugin的下载安装

    JMeter和JMeterPlugin的下载安装 Apache Jmeter是一个100%的纯Java桌面应用,主要是针对web的压力和性能测试,但后来扩展到其他测试领域.Jmeter可以用于测试FT ...

  3. 理解REST和SOA

    REST -- REpresentational State Transfer 直接翻译:表现层状态转移. 精辟理解:URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作 ...

  4. C#操作VFP的dbf数据库文件实例

    C#操作VFP的dbf数据库文件实例 新一篇: js获取网站跟路径 实例中分别使用Oledb和Odbc操作vfp数据库dbf文件,操作包括:读取,增删改. 已测试可直接使用,使用方法:下面代码分两个部 ...

  5. java工具类-excel jxl

    jxl-2.6.9.14.jarimport net.sf.jxls.transformer.XLSTransformer;//jxls-core-1.0.2.jarimport java.io.Fi ...

  6. JavaScript中的继承模式总结(九)

    一.总结: //js中的几种继承 //原型链的问题,包含引用类型的原型属性会被实例共享,子类型无法给超类型传递参数 function SuperType() { this.colors = [&quo ...

  7. HA 高可用mysql集群

    注意问题: 1.保持mysql用户和组的ID号是一致的: 2.filesystem 共享存储必须要有写入权限: 3.删除资源必须先删除约束,在删除资源: 1.安装数据库,这里使用maridb数据库: ...

  8. Appscan_web安全测试工具 (含修改启动浏览器的方法)

    安全测试应该是测试中非常重要的一部分,但他常常最容易被忽视掉. 尽管国内经常出现各种安全事件,但没有真正的引起人们的注意.不管是开发还是测试都不太关注产品的安全.当然,这也不能怪我们苦B的“民工兄弟” ...

  9. Python 天气预报+微信

    """ Description: 需要提供以下三个信息,在申请到的微信企业号当中可以找到 agentid corpid corpsecret Author:Nod Dat ...

  10. java.lang.ClassNotFoundException: org.I0Itec.zkclient.exception.ZkNoNodeException 异常 如何处理

    严重: Context initialization failed java.lang.NoClassDefFoundError: org/I0Itec/zkclient/exception/ZkNo ...