为了我自己的好奇心,我试图为定义地图[B](f:A => B)的所有类型定义
Haskell的liftM:M [A],但是我自己无法实现*.我希望能够更深入了解
Scala类型系统的人能够向我解释它.
首先,我尝试使用结构类型约束:
import language.higherKinds
import language.reflectiveCalls
def lift[A, B, F[_] <: {def map(f : A => B): F[B]}](a : F[A])(g : A => B) =
a map g
lift(Some(1)) {_ + 1} // error: inferred type arguments [Int,Nothing,Some] do not
// conform to method lift's type parameter bounds
// [A,B,F[_] <: AnyRef{def map(f: A => B): F[B]}]
我已经尝试了其他一些东西,但是永远无法获得接受类型定义映射的函数[B](f:A => B):F [B].我还通过特征对它进行了重击:
object Liftable {
import language.higherKinds
trait Mappable[A, F[_]] {
def map[B](f : A => B): F[B]
}
implicit class MappableOption[A](opt : Option[A]) extends Mappable[A, Option] {
def map[B](f : A => B) = opt map f
}
def lift[A, B, F[_]](a : Mappable[A, F])(f : A => B) =
a map f
}
import Liftable._
lift(Some(1)) {_ + 1} // Some(2)
lift(None:Option[Int]) {_ + 1} // None
这可行,但它需要为定义map函数的每个类型定义一个隐式类.它在那里失去了很多用处.我不确定是否有办法为定义地图的所有类型定义隐式转换 – 它让我回到了第一种方法遇到的问题.
我忽略了什么吗?是唯一可行的方法来执行此操作以遵循第二种方法,并为每个可映射类型单独定义隐式转换吗?
*我知道Scalaz库有一些为Functor特性定义的提升函数形式,但我只是通过浏览源代码完全无法理解它在整个库的上下文中是如何工作的.
最佳答案 选项地图方法签名:
def map[B](f: (A) ⇒ B): Option[B]
并且’提升’方法需要定义为:
def lift[A,C,F[A] <: {def map[B <: C](f : A => B):F[B]}] (a : F[A])(g : A => C)
= a map g
并致电:
lift(Option(1)){ _ + 1 }
res: Option[Int] = Some(2)