我正在定义一个具有抽象类型B的特征,我想将其用作monad。要指定B必须能够充当monad,我声明一个隐式的monadB
:
trait A {
type B[_]
implicit def monadB: Monad[B]
}
然后,当我实现此类型时,我将具体类型分配给B
,例如List
。然后,我需要为隐式monadB
提供具体的定义。例如,在下面的函数.point[B]
中调用方法randomDouble
时需要它。我该怎么办?
trait A2 extends A {
type B[_] = List[_]
implicit def monadB: Monad[B] = ???
def randomDouble: B[Double] = new Random.nextDouble.point[B]
}
我试过了:
implicit def monadB: Monad[B] = implicitly[Monad[B]]
但是这会在运行时卡在无限循环中,我想因为implicitly
本身依赖于相应的隐式值。我想我需要说Monad[B]
的隐含值实际上与Monad[List]
的隐含值相同,因为B[_] = List[_]
。但不幸的是,
implicit def monadB: Monad[B] = implicitly[Monad[List]]
也不起作用,因为Monad在它的类型参数中是不变的(如果我得到它,意味着Monad [List]不能用来代替Monad [B],即使B = List)
我被困住了。如何定义monadB
?
答案 0 :(得分:1)
您可能还需要考虑另外两种方式:
你可以简单地拥有:
def randomDouble[B[_]](implicit monadB: Monad[B]): B[Double] = (new Random).nextDouble.point[B]
然后你就可以这样使用它:println(randomDouble[List])
,所以你不要将randomDouble
绑定到任何特定的monad。
或者,如果你坚持使用特征:
trait A {
type B[_]
implicit def monadB: Monad[B]
}
trait A2 extends A {
def randomDouble: B[Double] = (new Random).nextDouble.point[B]
}
def a2[A[_]](implicit m: Monad[A]) = new A2 {
type B[C] = A[C]
implicit val monadB = m
}
然后你使用它println(a2[List].randomDouble)
再次将A2
或a2
绑定到任何特定的monad。
答案 1 :(得分:0)
事实证明,使用符号指定内部抽象类型而不是保留_
可以隐式使用[Monad [List]]:
trait A2 extends A {
type B[A] = List[A]
implicit def monadB: Monad[B] = implicitly[Monad[List]]
def randomDouble: B[Double] = new Random.nextDouble.point[B]
}
虽然它有效,但我没有任何解释原因。