sách gpt4 ai đã đi

scala - ADT 的类型类实例的通用派生

In lại 作者:行者123 更新时间:2023-12-04 21:35:56 27 4
mua khóa gpt4 Nike

假设我有一个 ADT 和类型类 FooGiống như thế này:

sealed trait A
case class A1() extends A
case class A2() extends A
case class A3() extends A

trait Foo[X] { def foo(x: X): String; }
object Foo {
implicit val a1foo = new Foo[A1] { def foo(a1: A1) = "A1" }
implicit val a2foo = new Foo[A2] { def foo(a2: A2) = "A2" }
implicit val a3foo = new Foo[A3] { def foo(a3: A3) = "A3" }
}

现在我可以写 Foo[A]像那样:
implicit val afoo = new Foo[A] {
def foo(a: A) = a match {
case a1 : A1 => a1foo.foo(a1)
case a2 : A2 => a2foo.foo(a2)
case a3 : A3 => a3foo.foo(a3)
}
}

不幸的是,这段代码太样板了。是否有可能摆脱所有样板并派生 Foo[A]自动(也许与 shapeless )?

1 Câu trả lời

这个afoo隐含在其他三个存在时不仅无用,而且甚至很糟糕,因为它会失败并返回 MatchErrorhiện hữu new A {}值(value)。

我不明白你为什么需要 Foo[A] 这样的实例当您有涵盖 MỘT 类型的所有可能(有效)值的隐式时和 afoo不添加任何东西。

我可以想象如果你有一个功能

def foo(a: A)(implicit f: Foo[A]): String = f.foo(a)

那么,当然, a1foo , a2foohoặc a3foo会适合。 afoo会的,所以 foo(A1())可以编译并正常工作,但是 foo(new A {})也将编译,并以 MatchError 失败.顺便说一句,如果调用 foo(new A {})存在于代码中,它将在编译时出现关于非详尽匹配的警告,但如果不是,它将静默编译。

所以解决这个问题的方法是修改 đồ ăn , 采用更精确的类型:
def foo[X <: A](a: X)(implicit f: Foo[X]): String = f.foo(a)

Hiện nay foo(A1())将编译并选择 a1foo (Và A2A3 相同),而 foo(new A {})只是不会编译(因为它不应该)。

làm mới

如果您仍想拥有 Foo[A] 的实例作为默认情况,您可以像这样更改代码:
object Foo extends Foo_1 {

implicit val a1foo: Foo[A1] = ...
implicit val a2foo: Foo[A2] = ...
implicit val a3foo: Foo[A3] = ...
}

trait Foo_1 {
// this implicit has a lower priority:
implicit val afoo: Foo[A] = new Foo[A] { def foo(a: A) = "A" }
}

Hiện nay foo(new A {})hoặc foo(A2(): A)将编译并返回 "A" .

附言顺便说一下,它是 recommended编写显式类型的隐式。

关于scala - ADT 的类型类实例的通用派生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38168044/

27 4 0
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com