[英]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.