Scalaz(30)- Free :Natural Tranformation ~> - map higher kinded types for free
2016-03-11 14:47
344 查看
当我们需要定义一些对应高阶类型进行相互类型转换的操作函数时,我们发现scala语言并不提供能定义这种函数的支持。举例来说:如果我们希望定义一个函数把对于任何T值的Option[T]转换成List[T]的话,我们可能这样定义:
看看hOptFun的类型:Option[Nothing] => List[Nothing], 即我们无法对T的类型进行限定。如果我们使用hOptFun:
结果是无法正常使用hOptFun。这就证明了scala是不支持高阶类型转换函数的。一个可行的方法是通过一个特殊类来实现高阶类型转换,这就是scalaz的NaturalTransformation类型的主要功能。scalaz的NaturalTransformation类型是这样定义的:scalaz/NaturalTransformation.scala
我们只需要实现apply就行了:
从optiontoListTrans.apply可以看出我们实际上直接调用了那个按我们要求实现的apply方法。换句话说:如果我们需要把F[A]与G[A]对应,我们可以通过实现apply的方式来表达它们具体的对应方式,这个apply方法就可以实现高阶类型的相互转换。
def toList[T](opt: Option[T]): List[T] = opt.toList //> toList: [T](opt: Option[T])List[T] val hOptFun = toList _ //> hOptFun : Option[Nothing] => List[Nothing] = <function1>
看看hOptFun的类型:Option[Nothing] => List[Nothing], 即我们无法对T的类型进行限定。如果我们使用hOptFun:
hOptFun(None) //> res0: List[Nothing] = List() //hOptFun(Some(10)) //type mismatch; found : Int(10) required: Nothing //hOptFun(Some("hi")) //type mismatch; found : String("hi") required: Nothing
结果是无法正常使用hOptFun。这就证明了scala是不支持高阶类型转换函数的。一个可行的方法是通过一个特殊类来实现高阶类型转换,这就是scalaz的NaturalTransformation类型的主要功能。scalaz的NaturalTransformation类型是这样定义的:scalaz/NaturalTransformation.scala
/** A universally quantified function, usually written as `F ~> G`, * for symmetry with `A => B`. * * Can be used to encode first-class functor transformations in the * same way functions encode first-class concrete value morphisms; * for example, `sequence` from [[scalaz.Traverse]] and `cosequence` * from [[scalaz.Distributive]] give rise to `([a]T[A[a]]) ~> * ([a]A[T[a]])`, for varying `A` and `T` constraints. */ trait NaturalTransformation[-F[_], +G[_]] { self => def apply[A](fa: F[A]): G[A] ...
我们只需要实现apply就行了:
val optionToListTrans = new (Option ~> List) { def apply[T](opt: Option[T]): List[T] = opt.toList } //> optionToListTrans : scalaz.~>[Option,List] = Exercises.naturaltransform$$an //| onfun$main$1$$anon$1@2d554825 optionToListTrans(None) //> res1: List[Nothing] = List() optionToListTrans(Some("hi")) //> res2: List[String] = List(hi) optionToListTrans.apply(3.some) //> res3: List[Int] = List(3)
从optiontoListTrans.apply可以看出我们实际上直接调用了那个按我们要求实现的apply方法。换句话说:如果我们需要把F[A]与G[A]对应,我们可以通过实现apply的方式来表达它们具体的对应方式,这个apply方法就可以实现高阶类型的相互转换。
相关文章推荐
- Android设计模式系列
- 20160309作业
- PreparedStatement
- AS版本手动升级
- CentOS常用的文件操作命令总结
- Objective-C总Runtime的 消息机制
- 《Android应用测试与调试实战》读书笔记
- 数据库基础
- CentOS下SVN服务的启动与关闭
- h264 分析工具
- [转]C# ListView 单击标题实现排序(在转载的基础上有所完善)
- [转]解决C# WinForm 中 VSHOST.EXE 程序不关闭的问题
- SQL杂记
- [LeetCode] Encode and Decode Strings 加码解码字符串
- SuperSocket中的Server是如何初Start的
- Mac升级Vim
- 打包测试 之 企业账号in-house分发ipa坑
- iOS开发---做tableview分级展示
- 判断输入的值是否为Double
- SQLServer修改表字段时进行表连接