Haskell语言学习笔记(61)Distributive
Distributive
class Functor g => Distributive g where
distribute :: Functor f => f (g a) -> g (f a)
distribute = collect id
collect :: Functor f => (a -> g b) -> f a -> g (f b)
collect f = distribute . fmap f
distributeM :: Monad m => m (g a) -> g (m a)
distributeM = fmap unwrapMonad . distribute . WrapMonad
collectM :: Monad m => (a -> g b) -> m a -> g (m b)
collectM f = distributeM . liftM f
cotraverse :: (Distributive g, Functor f) => (f a -> b) -> f (g a) -> g b
cotraverse f = fmap f . distribute
comapM :: (Distributive g, Monad m) => (m a -> b) -> m (g a) -> g b
comapM f = fmap f . distributeM
Distributive 是个类型类。功能上与 Traversable 类型类呈现对偶(dual)关系。
Traversable 类型将一个函数应用到多个数值,而
Distributive 类型将一个数值应用到多个函数。
((->)e) 是个 Distributive
instance Distributive ((->)e) where
distribute a e = fmap ($e) a
collect f q e = fmap (flip f e) q
Sum 是个 Distributive
instance Distributive Monoid.Sum where
collect = coerce (fmap :: (a -> b) -> f a -> f b)
:: forall f a b . Functor f
=> (a -> Monoid.Sum b) -> f a -> Monoid.Sum (f b)
distribute = Monoid.Sum . fmap Monoid.getSum
应用 Distributive
Prelude Data.Distributive> distribute [(+1),(+2)] 1
[2,3]
Prelude Data.Distributive> collect (^) [1,2] 3
[1,8]
Prelude Data.Distributive> cotraverse sum [(+1),(*2)] 3
10
Prelude Data.Distributive> comapM product [(+1),(*2)] 3
24
Prelude Data.Distributive Data.Monoid> distribute [Sum 1, Sum 2]
Sum {getSum = [1,2]}
Prelude Data.Distributive Data.Monoid> collect (\x->Sum[x]) [3,4]
Sum {getSum = [[3],[4]]}
手动计算
distribute [(+1),(+2)] 1
= fmap ($1) [(+1),(+2)]
= [1+1,1+2] = [2,3]
collect (^) [1,2] 3
= fmap (flip (^) 3) [1,2]
= fmap (^3) [1,2]
= [1^3,2^3] = [1,8]
cotraverse sum [(+1),(*2)] 3
= (fmap sum . distribute) [(+1),(*2)] 3
= sum $ distribute [(+1),(*2)] 3
= sum [4, 6] = 10
这里
(fmap f . g) x y
= (f . g x) y
= f $ g x y
Haskell语言学习笔记(61)Distributive的更多相关文章
- 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语言学习笔记(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 ...
- Haskell语言学习笔记(92)HXT
HXT The Haskell XML Toolbox (hxt) 是一个解析 XML 的库. $ cabal install hxt Installed hxt-9.3.1.16 Prelude&g ...
随机推荐
- Linux基本权限管理
一. 文件基本权限 1. - 文件类型,第一个字符为-,代表是文件类型(-文件 d目录 | 软链接文件) 2. 总共10个字符,2~10 总共9个字符,每三个字符为一组 rw- ...
- Openwrt TTL线刷
1.接通串口,网线: 2.打开串口软件SecureCRT: 3.按复位键,不断地出现信息: 4.2秒内按任意键停下来,出现uboot> 5.输入httpd 6.打开网页,输入ip 7.开始更新, ...
- PHP接口开发加密技术实例原理与例子
下面例子简单讲解PHP接口开发加密技术:如app要请求用户列表,api是“index.php?module=user&action=list”app生成token = md5sum (‘use ...
- python格式化输出 format
看图
- 大数据挖掘算法篇之K-Means实例
一.引言 K-Means算法是聚类算法中,应用最为广泛的一种.本文基于欧几里得距离公式:d = sqrt((x1-x2)^+(y1-y2)^)计算二维向量间的距离,作为聚类划分的依据,输入数据为二维数 ...
- appium+python自动化42-微信公众号
前言 本篇介绍如何在微信公众号上自动化测试,以操作我的个人公众号:yoyoketang为例,没关注的,先微信关注了,再跟着操作 环境准备: python 3.6 appium 1.7以上版本 微信6. ...
- Java\学习——字符串
import java.util.Scanner; public class cys1 { /** * @param args */ public static void main(String[] ...
- 学习笔记之数据库Database
SQL@Wiki http://en.wikipedia.org/wiki/SQL 一篇文章,掌握所有开源数据库的现状 - AI前线 https://mp.weixin.qq.com/s?__biz= ...
- spark1.0属性配置以及spark-submit简单使用
在spark1.0中属性支持三种配置方式: 1.代码 在代码中构造SparkConf时指定master.appname或者key-value等 val conf = new SparkConf(); ...
- Spark分析之BlockManager
BlockManager中存储block的流程: doPut()方法 入参:blockId, data, level, tellMaster 1)为block创建BlockInfo并加锁使其不能被 ...