Scalaz 7如何将Functor与Function1结合使用

时间:2019-05-04 03:21:14

标签: scala scalaz scalaz7

嗨,我正在注视着学习Scalaz。

我想获取一个函数并与另一个函数映射。

尽管我能写这个:

import scalaz._, Scalaz._

import std.function._
import syntax.monad._

((x: Int) => x + 1) map {_ * 7}

它起作用,当我按照github项目中的示例使用显式方法时,它不起作用(见下文)

import scalaz._, Scalaz._

import std.option._
import std.function._
import syntax.monad._

Functor[Function1[Int,Int]].map{x:Int => x * 4}{(x:Int) =>x * 7}

我得到错误

  

错误:(10,17)Function1需要两个类型参数,一个:   Functor [Function1] .map {x:Int => x * 4} {(x:Int)=> x * 7}

我确实从一个有效的文档示例中启发了自己

Functor[Option].map(Some("adsf"))(_.length)

2 个答案:

答案 0 :(得分:2)

我们得到((x: Int) => x * 4) map ((x: Int) => x * 7)的隐式扩展

ToFunctorOps(((x: Int) => x * 4))(function1Covariant) map ((x: Int) => x * 7)

function1Covariant的签名是

implicit def function1Covariant[T]: Monad[T => ?] with ...

Functor.apply的第一个签名是

def apply[F[_]](implicit F: Functor[F]): Functor[F] = F

F[_]替换为({type F[B] = Int => B})#F,或将kind-projector替换为Int => ?,我们使apply要求隐式

Functor[Int => ?]
由于function1Covariant[Int]: Monad[Int => ?]Monad的一种类型,因此Functor满足的

。这样我们就可以写清楚

Functor[({type F[B] = Int => B})#F].map((x: Int) => x * 4)((x: Int) => x * 7)

或使用kind-projector作为

Functor[Int => ?].map((x: Int) => x * 4)((x: Int) => x * 7)

答案 1 :(得分:0)

我接受了以上答案,因为它可以解决问题。它显示了如何做我想做的事。显式地将函数设为函子,以便在其上进行映射。但是,我对为什么必须为此功能({type F[B] = Int => B})#F感到有些不满意?为什么它不能完全通用,为什么该库没有开箱即用,而不是让用户这样做。

我相信我已经在以下帖子中找到了答案:

What are type lambdas in Scala and what are their benefits?

Why type lambdas?

基于此,我得出结论,只要您没有F [X](例如F [Int,INT]或Map [Int,INT]),该库就无法为您烘焙。需要手动求助于lambda类型,这会迫使您做部分操作。因此,对于FunctionX,我们无法在泛型库中添加一些通用的东西。