[英]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没有多态函数-任何函数值的输入和输出类型都必须是具体类型(但是,您可以具有返回函数的多态方法,并且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
部分设置为参数很困难),因此通常最好还是多态方法起作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.