捕获返回类型中的类型class
Capture type class in returning type
在下面的示例中,我必须重复 M
是一个 Monad
以便定义 bar
这似乎是不必要的,因为我已经按照我定义的方式告诉编译器 fnc
.
import scalaz._
import scalaz.Scalaz._
object MyTest {
// function returning a function accepting a monad as parameter
def fnc[M[_]: Monad, T](t: T): (M[T] => T) = xs => t
// this works
def bar[M[_]: Monad]: (M[Double] => Double) = fnc(1.0)
// I would like this also to work
val foo = fnc(1.0)
}
如何使 foo
成为接受任何 M[T]
的函数?
Scala 没有多态函数——任何函数值的输入和输出类型必须是具体类型(但是,你可以有 return 函数的多态方法,并且你的 fnc
和 bar
就是这样的例子)。这意味着您的 foo
定义仅在您指定具体的单子类型时才有效:
val foo: List[Double] => Double = fnc(1.0)
Shapeless 使用对象和隐式一起实现多态函数值:
import scalaz._, Scalaz._
object foo extends shapeless.Poly1 {
implicit def double[M[_]: Monad]: Case.Aux[M[Double], Double] = at(_ => 1.0)
}
然后:
scala> foo(List(1.0))
res0: Double = 1.0
scala> foo(Option(1.0))
res1: Double = 1.0
scala> foo(1.0: Id[Double])
res2: Double = 1.0
但不幸的是,由于语言的限制,对于如何定义这些多态函数值有很多限制(例如,很难将 1.0
部分作为参数),所以一般来说,让多态方法起作用可能会更好。
在下面的示例中,我必须重复 M
是一个 Monad
以便定义 bar
这似乎是不必要的,因为我已经按照我定义的方式告诉编译器 fnc
.
import scalaz._
import scalaz.Scalaz._
object MyTest {
// function returning a function accepting a monad as parameter
def fnc[M[_]: Monad, T](t: T): (M[T] => T) = xs => t
// this works
def bar[M[_]: Monad]: (M[Double] => Double) = fnc(1.0)
// I would like this also to work
val foo = fnc(1.0)
}
如何使 foo
成为接受任何 M[T]
的函数?
Scala 没有多态函数——任何函数值的输入和输出类型必须是具体类型(但是,你可以有 return 函数的多态方法,并且你的 fnc
和 bar
就是这样的例子)。这意味着您的 foo
定义仅在您指定具体的单子类型时才有效:
val foo: List[Double] => Double = fnc(1.0)
Shapeless 使用对象和隐式一起实现多态函数值:
import scalaz._, Scalaz._
object foo extends shapeless.Poly1 {
implicit def double[M[_]: Monad]: Case.Aux[M[Double], Double] = at(_ => 1.0)
}
然后:
scala> foo(List(1.0))
res0: Double = 1.0
scala> foo(Option(1.0))
res1: Double = 1.0
scala> foo(1.0: Id[Double])
res2: Double = 1.0
但不幸的是,由于语言的限制,对于如何定义这些多态函数值有很多限制(例如,很难将 1.0
部分作为参数),所以一般来说,让多态方法起作用可能会更好。