如何编写具有上下文边界的第一类函数,可以在使用站点干净地调用?

时间:2011-11-01 15:37:32

标签: scala scalaz typeclass

例如,假设我想编写一个函数length,它返回给定结构的长度,因为它在范围内有一个类型为Length的类型的实例(来自Scalaz)。 / p>

这就是我目前的定义方式:

scala> def length[A, F[_] : Length]: F[A] => Int = _.len
length: [A, F[_]](implicit evidence$1: scalaz.Length[F])F[A] => Int

但是length(List(2, 3))之类的调用失败了,因为在这种情况下隐式参数是第一个需要的参数。

scala> length(List(2, 3))
<console>:15: error: type mismatch;
 found   : List[Int]
 required: scalaz.Length[?]
              length(List(2, 3))
                         ^

我认为length(implicitly)(List(2, 3))会起作用,但最终会导致崩溃(这可以理解为类型推断从左向右流动)。提供明确的类型注释有效,但它难以忍受。

scala> length(implicitly[Length[List]])(List(2, 3))
res16: Int = 2

是否有一种很好的方法来编写第一类函数,例如length,具有上下文绑定,可以像使用站点上的常规函数​​一样干净地调用它? (如length(List(2, 3))

1 个答案:

答案 0 :(得分:6)

容易,欺骗!

scala> def length[A, F[_] : Length]: F[A] => Int = _.len
length: [A, F[_]](implicit evidence$1: scalaz.Length[F])F[A] => Int

scala> List(2, 3) |> length
res0: Int = 2