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的更多相关文章

  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语言学习笔记(49)ByteString Text

    Data.ByteString String 是 [Char] 的同义词,在使用上存在List的惰性所带来的性能问题. 在处理大型二进制文件时,可以使用 ByteString 来代替 String. ...

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

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

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

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

随机推荐

  1. 栈的一个实例——Dijkstra的双栈算术表达式求值法

    Dijkstra的双栈算术表达式求值法,即是计算算术表达式的值,如表达式(1 + ( (2+3) * (4*5) ) ). 该方法是 使用两个栈分别存储算术表达式的运算符与操作数 忽略左括号 遇到右括 ...

  2. java数组变量

    数组变量是一种引用类型的变量,能够指向数组对象.数组对象存储在堆内存中,当数组变量为局部变量时存储在栈内存中. int[] p = new int[]{5, 6, 7, 8, 9}; p是数组变量,指 ...

  3. JS给HTML5页面<Select></Select>绑定选中项

    获取选中值: function setApprovalPersonName() { var name = $("#approvalPersion").find("opti ...

  4. RK3288 mipi屏调试流程

    CPU:RK3288 系统:Android 5.1 1.修改kernel/arch/arm/configs/rockchip_defconfig,打开mipi屏开关 # CONFIG_LCD_GENE ...

  5. centos7下svn的安装与配置

    1.环境 centos7 2.安装svnyum -y install subversion 3.配置 建立版本库目录mkdir /www/svndata svnserve -d -r /www/svn ...

  6. 异步FIFO空满设计延迟问题

    由于设计的时候读写指针用了至少两级寄存器同步,同步会消耗至少两个时钟周期,势必会使得判断空或满有所延迟,这会不会导致设计出错呢? 异步FIFO通过比较读写指针进行满空判断,但是读写指针属于不同的时钟域 ...

  7. Hadoop专业解决方案-第1章 大数据和Hadoop生态圈

    一.前言: 非常感谢Hadoop专业解决方案群:313702010,兄弟们的大力支持,在此说一声辛苦了,经过两周的努力,已经有啦初步的成果,目前第1章 大数据和Hadoop生态圈小组已经翻译完成,在此 ...

  8. pycharm中配置pep8

    Pycharm本身是有pep8风格检测的,当你敲得代码中不符合规范时,会有下划波浪线提示.如何让代码修改为符合规范,去掉这些难看的波浪线呢? 1.安装autopep8  pip install aut ...

  9. Python软件开发规范

    bin  整个程序的执行路口    start.py conf 配置文件     setting.py lib   库  模块与包    common.py    sql.py core  核心逻辑  ...

  10. word2vec剖析,资料整理备存

    声明:word2vec剖析,资料整理备存,以下资料均为转载,膜拜大神,仅作学术交流之用. word2vec是google最新发布的深度学习工具,它利用神经网络将单词映射到低维连续实数空间,又称为单词嵌 ...