从"Scala in Action"中输入投影示例(第8章)

Max*_*Max 5 types scala

任何人都可以帮助我从书中下面的代码位?

trait Mapper[F[_]] {
  def fmap[A, B](xs: F[A], f: A => B): F[B]   
}

def VectorMapper = new Mapper[Vector] {
  def fmap[A, B](xs: Vector[A], f: A => B): Vector[B] = xs map f 
}
Run Code Online (Sandbox Code Playgroud)

这很简单:特性定义使用更高级的类型F[_]用于任何"类容器"类型,然后用于具体的映射器Vector.

然后是一个棘手的部分.映射器Either.据我所知{type E[A] = Either[X, A]},正如一个代码块,和({type E[A] = Either[X, A]})#E作为投影这需要该类型的别名E出的代码匿名块的和由作者"隐藏"的存在X对于Mapper因为性状上单一类型的参数"的容器类型"操作性状只- 我们感兴趣A,即Right.

def EitherMapper[X] = new Mapper[({type E[A] = Either[X, A]})#E ] {
    def fmap[A, B](r: Either[X, A], f: A => B): Either[X, B] = r match {
        case Left(a) => Left(a)
        case Right(a) => Right(f(a))
    }     
}
Run Code Online (Sandbox Code Playgroud)

问题: 我们为什么需要X这个def EitherMapper[X] =部分?

谢谢你的详细信息

Vin*_*gio 4

例如,两者都依赖于两种类型Either[Int, String]

EitherMapper是一个仅依赖于一种类型的类型构造函数,因此当您有 a 时EitherMapper[Int],您正在处理 a Either[Int, A],并且A被解析为 Mapper 部分,这样您就可以拥有任何A=>B函数,因为第一种类型Either已经存在于映射器和你返回一个Either[X, B].

事实上,类型 E[A] 相当于 Either[X, A],关于类型只有一个自由度!

val right: Either[Boolean, String] = Right("test")
val left: Either[Boolean, String] = Left(false)

println(EitherMapper.fmap(right, (s: String) => s.length))
> Right(4)
println(EitherMapper.fmap(left, (s: String) => s.length))
> Left(false)
Run Code Online (Sandbox Code Playgroud)

在本例中,类型为EitherMapper[Boolean], fmap 的类型为fmap[String, Integer],它接受Either[Boolean, String]并返回Either[Boolean, Integer]

X正如您所看到的, fmap 的类型在类型部分上没有说明任何内容Either[X, A],因此最终您可以将该 (s: String) => s.length)函数用于其他EitherMapper[X]类型,简单来说,任一类型的“左侧”部分可以是您想要的任何内容,它是类型结构的“X”部分。

希望现在更清楚了!