Scalaz(29)- Free :Coyoneda - Functor for free
很多时候我们会遇到一些高阶类型F[_],但又无法实现它的map函数,也就是虽然形似但F不可能成为Functor。看看下面的例子:
trait Interact[A]
case class Ask(prompt: String) extends Interact[String]
case class Tell(msg: String) extends Interact[Unit]
Interact类型只容许两种实例:Ask继承了Interact[String], Tell继承Interact[Unit]。我们无法获取map[A,B]函数的B值,因而无法实现map函数了。但是,往往在一些场合里我们需要把F当做Functor来使用,如用Free Structure把F升格成Monad。也就是说我们需要把Interact当做Functor才能构建一个基于Interact的Free Monad。Scalaz里的Coyoneda与任何F[_]类型成同构(互等),而Coyoneda是个Functor,这样我们可以用Coyoneda来替代F。在上面的例子里我们只要得出F的Coyoneda,然后我们就可以用这个Coyoneda来替代F,因为它们是同构的。我们来看看Coyoneda的定义:scalaz/Coyoneda.scala
sealed abstract class Coyoneda[F[_], A] { coyo =>
/** The pivot between `fi` and `k`, usually existential. */
type I
/** The underlying value. */
val fi: F[I]
/** The transformer function, to be lifted into `F` by `run`. */
val k: I => A
...
/** Like `lift(fa).map(_k)`. */
def apply[F[_], A, B](fa: F[A])(_k: A => B): Aux[F, B, A] =
new Coyoneda[F, B]{
type I = A
val k = _k
val fi = fa
}
...
type Aux[F[_], A, B] = Coyoneda[F, A] {type I = B}
/** `F[A]` converts to `Coyoneda[F,A]` for any `F` */
def lift[F[_],A](fa: F[A]): Coyoneda[F, A] = apply(fa)(identity[A])
即使F不是Functor,我们还是可以把F[A]拆成Coyoneda[F,A]。而Coyoneda和F同构,看下面scalaz里的代码:
type CoyonedaF[F[_]] = ({type A[α] = Coyoneda[F, α]})
import Isomorphism._
def iso[F[_]: Functor]: CoyonedaF[F]#A <~> F =
new IsoFunctorTemplate[CoyonedaF[F]#A, F] {
def from[A](fa: F[A]) = lift(fa)
def to[A](fa: Coyoneda[F, A]) = fa.run
}
我们自己同样可以用更简单的方法来证明:
object proof_coyo {
trait _Coyoneda[F[_],A] {
type I
def k: I => A
def fi: F[I]
}
def toCoyo[F[_],A](fa: F[A]) =
new _Coyoneda[F, A] {
type I = A
val k = (a: A) => a
val fi = fa
}
def fromCoyo[F[_]: Functor,A](coyo: _Coyoneda[F,A]): F[A] =
Functor[F].map(coyo.fi)(coyo.k)
}
对于任何类型F及A, 我们通过toCoyo, fromCoyo可以证明_Coyoneda和F[A]同构。 既然Coyoneda和F[A]同构,那么我们可以这样表述:F[A] >>> Coyoneda[F,A]。也就是说我们可以在任何地方用Coyoneda[F,A]替代F[A]。上面例子中的Interact也可以用Coyoneda替代:
trait Interact[A]
case class Ask(prompt: String) extends Interact[String]
case class Tell(msg: String) extends Interact[Unit] type coyoInteract[A] = Coyoneda[Interact,A]
Scalaz(29)- Free :Coyoneda - Functor for free的更多相关文章
- Scalaz(25)- Monad: Monad Transformer-叠加Monad效果
中间插播了几篇scalaz数据类型,现在又要回到Monad专题.因为FP的特征就是Monad式编程(Monadic programming),所以必须充分理解认识Monad.熟练掌握Monad运用.曾 ...
- Scalaz(40)- Free :versioned up,再回顾
在上一篇讨论里我在设计示范例子时遇到了一些麻烦.由于Free Monad可能是一种主流的FP编程规范,所以在进入实质编程之前必须把所有东西都搞清楚.前面遇到的问题主要与scalaz Free的Free ...
- Scalaz(39)- Free :a real monadic program
一直感觉FP比较虚,可能太多学术性的东西,不知道如何把这些由数学理论在背后支持的一套全新数据类型和数据结构在现实开发中加以使用.直到Free Monad,才真正感觉能用FP方式进行编程了.在前面我们已 ...
- Scalaz(34)- Free :算法-Interpretation
我们说过自由数据结构(free structures)是表达数据类型的最简单结构.List[A]是个数据结构,它是生成A类型Monoid的最简单结构,因为我们可以用List的状态cons和Nil来分别 ...
- Scalaz(33)- Free :算式-Monadic Programming
在任何模式的编程过程中都无法避免副作用的产生.我们可以用F[A]这种类型模拟FP的运算指令:A是可能产生副作用的运算,F[_]是个代数数据类型ADT(Algebraic Data Type),可以实现 ...
- Scalaz(9)- typeclass:checking instance abiding the laws
在前几篇关于Functor和Applilcative typeclass的讨论中我们自定义了一个类型Configure,Configure类型的定义是这样的: case class Configure ...
- Scalaz(44)- concurrency :scalaz Future,尚不完整的多线程类型
scala已经配备了自身的Future类.我们先举个例子来了解scala Future的具体操作: import scala.concurrent._ import ExecutionContext. ...
- Scalaz(43)- 总结 :FP就是实用的编程模式
完成了对Free Monad这部分内容的学习了解后,心头豁然开朗,存在心里对FP的疑虑也一扫而光.之前也抱着跟大多数人一样的主观概念,认为FP只适合学术性探讨.缺乏实际应用.运行效率低,很难发展成现实 ...
- Scalaz(41)- Free :IO Monad-Free特定版本的FP语法
我们不断地重申FP强调代码无副作用,这样才能实现编程纯代码.像通过键盘显示器进行交流.读写文件.数据库等这些IO操作都会产生副作用.那么我们是不是为了实现纯代码而放弃IO操作呢?没有IO的程序就是一段 ...
随机推荐
- ssh(sturts2_spring_hibernate) 框架搭建之hibernate2
一.今天要进行解答的是对上次hibernate1进行进一步的完善,这次第一是进一步使用spring注入一个SessionFactory实例,避免了自己new实例:第二是应用数据库池(c3p0). 二. ...
- 使用jasperreports-5.6.0.jar导致的问题
使用jasperreports-5.6.0.jar导致的问题 Struts2+jasperReport5.6如下设置: <!-- 社员档案 --> <package name=&qu ...
- webpack学习笔记
1.安装webpack npm install webpack -g 2.进入项目目录,初始化 npm init 3.将webpack安装到项目依赖中 npm install webpack --sa ...
- JavaScript起点(严格模式深度了解)
格模式(Strict Mode)是ECMAScript5新增的功能,目前所有的主流浏览器的最新版本——包括IE10与Opera12——都支持严格模式,感兴趣的朋友可以了解下啊,希望本文对你有所帮助 严 ...
- android rectF
new Rect(left , top, right , bottom) 这个构造方法需要四个参数这四个参数 指明了什么位置 ?我们就来解释怎么画 这个 矩形 这四个 参数 分别代表的意思是:left ...
- 深入理解javascript函数系列第二篇——函数参数
× 目录 [1]arguments [2]内部属性 [3]函数重载[4]参数传递 前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传 ...
- Hadoop阅读笔记(六)——洞悉Hadoop序列化机制Writable
酒,是个好东西,前提要适量.今天参加了公司的年会,主题就是吃.喝.吹,除了那些天生话唠外,大部分人需要加点酒来作催化剂,让一个平时沉默寡言的码农也能成为一个喷子!在大家推杯换盏之际,难免一些画面浮现脑 ...
- Linux 启动过程分析
本文仅简单介绍Linux的启动过程,在此基础上做简要的分析.对于Linux启动过程中内部详细的函数调用不做介绍,只是希望本文能给新手起到一个抛砖引玉的作用,以便深入研究Linux的启动过程.下图基本展 ...
- redis学习之三配置文件redis.conf 的含义
摘自http://www.runoob.com/redis/redis-conf.html 安装redis之后的第一件事,我就开始配置密码,结果总是不生效,而我居然还没想到原因.今天突然用命令行设置了 ...
- 阅读《LEARNING HARD C#学习笔记》知识点总结与摘要二
今天继续分享我的阅读<LEARNING HARD C#学习笔记>知识点总结与摘要二,仍然是基础知识,但可温故而知新. 七.面向对象 三大基本特性: 封装:把客观事物封装成类,并隐藏类的内部 ...