如何定义 Monad 的隐式转换器?
How to define an implicit converter to a Monad?
我正在定义一个具有抽象类型 B 的特征,我想将其用作 monad。为了指定 B 必须能够充当 monad,我声明了一个隐式的 monadB
:
trait A {
type B[_]
implicit def monadB: Monad[B]
}
然后,我在实现这个类型的时候,给B
分配一个具体的类型,比如List
。然后我需要为隐式 monadB
提供一个具体的定义。例如,在下面的函数 randomDouble
中调用方法 .point[B]
时需要它。我该怎么做?
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 =名单)。
我卡住了。我如何定义 monadB
?
事实证明,用一个符号指定内部抽象类型而不是留下一个_
使得隐式使用成为可能[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]
}
虽然有效,但我无法解释原因。
您还可以考虑其他两种方式:
你可以简单地拥有:
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。
我正在定义一个具有抽象类型 B 的特征,我想将其用作 monad。为了指定 B 必须能够充当 monad,我声明了一个隐式的 monadB
:
trait A {
type B[_]
implicit def monadB: Monad[B]
}
然后,我在实现这个类型的时候,给B
分配一个具体的类型,比如List
。然后我需要为隐式 monadB
提供一个具体的定义。例如,在下面的函数 randomDouble
中调用方法 .point[B]
时需要它。我该怎么做?
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 =名单)。
我卡住了。我如何定义 monadB
?
事实证明,用一个符号指定内部抽象类型而不是留下一个_
使得隐式使用成为可能[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]
}
虽然有效,但我无法解释原因。
您还可以考虑其他两种方式:
你可以简单地拥有:
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。