Haskell语言学习笔记(45)Profunctor
Profunctor
class Profunctor p where
dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
dimap f g = lmap f . rmap g
lmap :: (a -> b) -> p b c -> p a c
lmap f = dimap f id
rmap :: (b -> c) -> p a b -> p a c
rmap = dimap id
Profunctor(逆变协变函子) 是个类型类。
Profunctor类型类带两个类型参数,第一个逆变,第二个协变。
Profunctor类型类包含三个函数。
- dimap :: (a -> b) -> (c -> d) -> p b c -> p a d
dimap函数同时修改 Profunctor 的两个参数。 - lmap :: (a -> b) -> p b c -> p a c
lmap函数只修改 Profunctor 的第一个参数。 - rmap :: (b -> c) -> p a b -> p a c
rmap函数只修改 Profunctor 的第二个参数。
Profunctor类型类实际上将输入输出的概念一般化。
Profunctor p b c 对于输入 b 是逆变,对于输出 c 则是协变。
Profunctor 的法则
法则
dimap id id ≡ id
lmap id ≡ id
rmap id ≡ id
dimap f g ≡ lmap f . rmap g
推论
dimap (f . g) (h . i) ≡ dimap g h . dimap f i
lmap (f . g) ≡ lmap g . lmap f
rmap (f . g) ≡ rmap f . rmap g
(->) 是个Profunctor
instance Profunctor (->) where
dimap ab cd bc = cd . bc . ab
lmap = flip (.)
rmap = (.)
Prelude Data.Profunctor> lmap (+2) (*3) $ 4
18
Prelude Data.Profunctor> rmap (+3) (*3) $ 4
15
Prelude Data.Profunctor> dimap (+2) (+3) (*3) $ 4
21
- (->) 是个典型的Profunctor,它具有输入和输出。
- lmap (+2) (*3) $ 4 = (4+2)*3 = 18
- rmap (+3) (*3) $ 4 = 4*3+3 = 15
- dimap (+2) (+3) (*3) $ 4 = (4+2)*3+3 = 21
- dimap (+2) (+3) (*3) = (+3) . (*3) . (+2)
Star 是个 Profunctor
newtype Star f d c = Star { runStar :: d -> f c }
instance Functor f => Profunctor (Star f) where
dimap ab cd (Star bfc) = Star (fmap cd . bfc . ab)
lmap k (Star f) = Star (f . k)
rmap k (Star f) = Star (fmap k . f)
Star 类型将 Functor 正向提升为 Profunctor
- newtype Star f d c = Star { runStar :: d -> f c }
Star 封装了一个输出为 Functor 的函数: d -> f c。 - dimap ab cd (Star bfc) = Star (fmap cd . bfc . ab)
dimap 函数将第一个函数 ab 应用到函数的输入端,将第二个函数 cd 应用到函数的输出端(通过fmap)。
Prelude Data.Profunctor> runStar (dimap (+1) show (Star Just)) 5
Just "6"
Prelude Data.Profunctor> runStar (dimap (+1) show (Star (\x -> [x, x+1]))) 5
["6","7"]
runStar (dimap (+1) show (Star Just)) 5 = fmap show . Just . (+1) $ 5
Costar 是个 Profunctor
newtype Costar f d c = Costar { runCostar :: f d -> c }
instance Functor f => Profunctor (Costar f) where
dimap ab cd (Costar fbc) = Costar (cd . fbc . fmap ab)
lmap k (Costar f) = Costar (f . fmap k)
rmap k (Costar f) = Costar (k . f)
Costar 类型将 Functor 反向提升为 Profunctor。
- newtype Costar f d c = Costar { runCostar :: f d -> c }
Costar 封装了一个输入为 Functor 的函数: f d -> c。 - dimap ab cd (Costar fbc) = Costar (cd . fbc . fmap ab)
dimap 函数将第一个函数 ab 应用到函数的输入端(通过fmap),将第二个函数 cd 应用到函数的输出端。
Prelude Data.Profunctor> runCostar (dimap (+1) show (Costar sum)) [1,2,3]
"9"
Prelude Data.Profunctor> runCostar (dimap (+1) show (Costar Data.Maybe.fromJust)) (Just 3)
"4"
runCostar (dimap (+1) show (Costar sum)) [1,2,3] = show . sum . fmap (+1) $ [1,2,3]
Forget 是个 Profunctor
newtype Forget r a b = Forget { runForget :: a -> r }
instance Profunctor (Forget r) where
dimap f _ (Forget k) = Forget (k . f)
lmap f (Forget k) = Forget (k . f)
rmap _ (Forget k) = Forget k
Haskell语言学习笔记(45)Profunctor的更多相关文章
- Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
- Haskell语言学习笔记(79)lambda演算
lambda演算 根据维基百科,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...
- Haskell语言学习笔记(69)Yesod
Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...
- Haskell语言学习笔记(20)IORef, STRef
IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...
- Haskell语言学习笔记(39)Category
Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...
- Haskell语言学习笔记(72)Free Monad
安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...
- Haskell语言学习笔记(49)ByteString Text
Data.ByteString String 是 [Char] 的同义词,在使用上存在List的惰性所带来的性能问题. 在处理大型二进制文件时,可以使用 ByteString 来代替 String. ...
- Haskell语言学习笔记(44)Lens(2)
自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...
- Haskell语言学习笔记(38)Lens(1)
Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...
随机推荐
- 创建对象的一种方式&一种继承机制(代码实例)
/* 创建对象的一种方式:混合的构造函数/原型方式, *用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法) */ function People(sname){ this.nam ...
- Joyoi公路乘车(原tyvj1015)
题目:http://www.joyoi.cn/problem/tyvj-1015 水题.连优化都不用. #include<iostream> #include<cstdio> ...
- linux 信号处理 一 (基本概念)
信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用信号,以及有关信号的几个系统调用. 信号机制是进程之间相互传递消息的一种方法,信号全 ...
- java工具类-excel jxl
jxl-2.6.9.14.jarimport net.sf.jxls.transformer.XLSTransformer;//jxls-core-1.0.2.jarimport java.io.Fi ...
- spring boot学习(2) SpringBoot 项目属性配置
第一节:项目内置属性 application.properties配置整个项目的,相当于以前的web.xml: 注意到上一节的访问HelloWorld时,项目路径也没有加:直接是http://loca ...
- 阿里云启用IPV6
ping过别人的IPv6网址之后,可以确定,局域网是不支持IPv6的.所以要使用隧道技术建立两台机器之间的IPv6连接 1.发现测试用服务器上没有IPv6地址.所以测试服务器的内核应该是没有IPv6模 ...
- Linux下不同颜色文件的类型
蓝色表示目录: 绿色表示可执行文件: 红色表示压缩文件: 浅蓝色表示链接文件:主要是使用ln命令建立的文件 灰色表示其它文件: 红色闪烁表示链接的文件有问题了: 黄色是设备文件,包括block, ch ...
- [UE4] C++实现Delegate Event实例(例子、example、sample)
转自:http://aigo.iteye.com/blog/2301010 虽然官方doc上说Event的Binding方式跟Multi-Cast用法完全一样,Multi-Cast论坛上也有很多例子, ...
- git 上传本地代码到github 服务器
git init git add . (所有文件用 点表示) git commit -m "注释语句" git remote add origin https://github.c ...
- Hadoop(1.2.1)安装
背景知识: 1.数据分布存储,不是复制存储 2.数据不动,代码动,由于分布式存储,所以把代码移动到数据的地方计算. 3.数据如何分割,hadoop提供的分割文件的编程接口 安装: 1.安装JDK 1. ...