gpt4 book ai didi

scala - 幺半群如何泛化类型

转载 作者:行者123 更新时间:2023-12-04 12:53:25 25 4
gpt4 key购买 nike

当我看到幺半群运算以一种自然的方式扩展到元组时,我在 Scala 中玩弄猫的 Monoids:

import cats.Monoid

object mon {
implicit object IntMonoid extends Monoid[Int] {
def combine(a: Int, b: Int) = a*a + b*b
def empty = 0
}

implicit object ListMonoid extends Monoid[List[Int]] {
def combine(a: List[Int], b: List[Int]): List[Int] =
a.zip(b).map(z => z._1 * z._2)
def empty = List(1)
}

def comb[T](a: T, b: T)(implicit m: Monoid[T]) =
m.combine(a, b)
}

val list1 = List(1, 2, 3)
val list2 = List(2, 3, 4)
println(mon.comb(list1, list2)) // outputs: List(2, 6, 12) as expected

val int1 = 2
val int2 = 4
println(mon.comb(int1, int2)) // outputs: 20 as expected

val x = (list1, int1)
val y = (list2, int2)
println(mon.comb(x, y)) // outputs: (List(2, 6, 12),20)
最后的输出应该以“自然”的方式出现,但是 de 编译器怎么知道怎么做呢?
我一直在尝试在 Cats 的源代码中寻找它,但我在 Scala 方面的经验不足,无法知道要寻找什么。我想同样的方法适用于类似的结构,如半群。

最佳答案

您的问题归结为泛型类型的类型类的隐式派生如何工作;所以让我们看两个例子:

A case where we want to provide an instance no matter what the generic is:


// Similar to the code you had, but without being tied to just List[Int],
// Since in this case the Int part is irrelevant.
implicit def monoidList[A]: Monoid[List[A]] =
new Monoid[List[A]] {
override final val empty: List[A] = Nil

override final def combine(l1: List[A], l2: List[A]): List[A] =
l1 ::: l2
}

A case where we require a proof of the generic type to provide the instance of the complex type:


implicit def optionMonoid[A](implicit aMonoid: Monoid[A]): Monoid[Option[A]] =
new Monoid[Option[A]] {
override final val empty: Option[A] = None

override final def combine(o1: Option[A], o2: Option[A]): Option[A] =
(o1, o2) match {
case (None, None) => None
case (Some(a), None) => Some(a)
case (None, Some(a)) => Some(a)
case (Some(a1), Some(a1)) => Some(aMonoid.combine(a1, a2))
}
}
因此,您现在可以想象 Monoid[Tuple2[A, B]]工作,但只是为了完整性,代码将是这样的:
implicit def tuple2Monoid[A, B](implicit aMonoid: Monoid[A], bMonoid: Monoid[B]): Monoid[(A, B)] =
new Monoid[(A, B)] {
override final def empty: (A, B) =
(aMonoid.empty, bMonoid.empty)

override final def combine(t1: (A, B), t2: (A, B)): (A, B) =
(t1, t2) match {
case ((a1, b1), (a2, b2)) => (aMonoid.combine(a1, a2), bMonoid.combine(b1, b2))
}
}

关于scala - 幺半群如何泛化类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69380976/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com