5

任何人都可以帮助我解决书中的以下代码位吗?

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 
}

这很简单:特征定义使用更高种类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))
    }     
}

问题: 为什么我们需要Xdef EitherMapper[X] =零件?

感谢您提供详细信息。

4

1 回答 1

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)

在这种情况下,类型是EitherMapper[Boolean],fmap 的类型是fmap[String, Integer],它接受Either[Boolean, String]并返回Either[Boolean, Integer]

X正如你所看到的 fmap的类型并没有说明类型的任何内容,Either[X, A]所以最后你可以将该 (s: String) => s.length)函数用于其他EitherMapper[X]类型,简单来说,任何一种类型的“左”部分都可以是你想要的任何东西,它是类型构造的“X”部分。

希望现在更清楚了!

于 2013-08-11T17:23:52.513 回答