如何定义 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) 并且你不会将 A2a2 绑定到任何特定的 monad。