4

为了我自己的好奇心,我尝试liftM为所有定义的类型定义 Haskell map[B](f : A => B): 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]}]

我在这方面尝试了其他一些事情,但永远无法获得接受类型定义的函数map[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它在那里失去了很多用处。我不确定是否有办法为所有定义的类型定义隐式转换map——这让我回到了第一种方法时遇到的问题。

我忽略了什么吗?遵循第二种方法并为每个可映射类型单独定义隐式转换的唯一可行方法是吗?


* 我知道Scalazlift库为其特性定义了某种形式的函数Functor,但我无法通过浏览源代码来完全理解它在整个库的上下文中是如何工作的。

4

1 回答 1

2

选项映射方法签名:

def map[B](f: (A) ⇒ B): Option[B]

而' lift '方法需要定义为:

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)
于 2013-11-05T10:08:38.423 回答