类型类一致性是一个众所周知的问题。
例如,Monad必须是Functor,Traversable也必须是Functor。如果has to be是通过继承(Monad[F[_]] extends Functor[F[_]])表示的,那么隐式解析中很可能会有歧义。
我应用了经验法则:如果你在继承方面有问题,就用委托来代替它。下面是一个示例:
trait Semigroup[A] {
def append(a: A, b: A): A
}
trait Monoid[A] {
def zero(): A
val semigroup: Semigroup[A]
def append(a: A, b: A): A = semigroup.append(a, b)
}
implicit object IntSemigroup extends Semigroup[Int] {
override def append(a: Int, b: Int): Int = a + b
}
implicit object IntMonoid extends Monoid[Int] {
override def zero(): Int = 0
override val semigroup: Semigroup[Int] = IntSemigroup
}
def main(args: Array[String]): Unit = {
println(implicitly[Monoid[Int]].append(2, 3))
}我猜这种方法不起作用,因为它很明显,但没有在scalaz/cat中使用。你能给我指出问题所在吗?
发布于 2018-05-26 06:11:55
通过使用继承来表示它,您可以免费获得推断-- Monad自动成为Functor。使用委托来表示它,你不需要。
你必须定义大量的隐式转换来解决这个问题,这将是一件痛苦的事情。但是(简单的)隐式转换不会在Scala中自动链接,所以使用它们,仍然不能通过中间类型类Applicative从Monad推断Functor。
附注:在实践中,如果你做对了事情,你通常在解决问题时不会有歧义。这意味着,(a)使用foo.some而不是Some(foo)等,以及(b)使用值类或类似的方法来消除您希望使用不同实例的类型的语义歧义。如果其他方法都失败了,显式地传入实例(在Haskell中不能这样做)。
https://stackoverflow.com/questions/50537107
复制相似问题