具有多个值的联积

Coproduct with multiple values

我正在玩无形的余积,但我不知道我是否用错了,但我不知道如何创建具有多个值的余积

有这个代码

 case class Name(value: String)

  case class Age(value: Int)

  case class Sex(value: String)

  type Person = Name :+: Age :+: Sex :+: CNil

  @Test
  def main(): Unit = {
    val person = Coproduct[Person](Name("Paul"))
    println(person.select[Name])
    println(person.select[Age])
    println(person.select[Sex])
  }

如何使用联积创建具有姓名、年龄和性别的人?

此致。

余积和积是根植于范畴论的两个对偶结构,但在编程术语中可以简化为:

  • 产品包括 所有 给定类型
  • coproduct 实现了 一个 给定类型

例如,一个由姓名、年龄和性别组成的人应该是使用产品类型的模型字段。这是因为一个人是由姓名、年龄和性别组成的; 所有这些类型是构建一个人所需要的。

联积的示例可以是任何具有子类型关系的事物,例如水果可以是苹果、香蕉或橙子。我们还经常将联积用于可能失败的结果类型,例如响应可以是成功或失败。 Either 和 Future 是联积的两个例子。

当您真正需要一个产品时,您将这些东西混合了一点,并为一个副产品建模(从语言语法的角度来看,这是完全正确的)。如果您 运行 您的代码,您将看到

Some(Name(Paul))
None
None

这是因为您的 Person 编码方式是姓名、年龄或性别。只有其中之一。然后你通过创建一个名字创建了一个 Person 的实例,这很好,所以如果你打印这三个选择你会看到名字选择器给你 Some(Name(Paul)),而其他两个是空的。

如果您将 Person 编码为产品(在通过异构列表实现的 shapeless 中),您将得到:

case class Name(value: String)
case class Age(value: Int)
case class Sex(value: String)

type Person = HNil

val person = Name("Paul") :: Age(32) :: Sex("Yes please") :: HNil

println(person) // Name(Paul) :: Age(32) :: Sex(Yes please) :: HNil

在普通的 Scala 中,我们可以使用 Either 等构造或通过子类型层次结构(例如特征 Fruit 由 case 类 Apple、Banana 等扩展)来建模联积,而产品通常仅通过 case 建模类(在您的情况下为 case class Person(name: String, age: Int, sex: String)

在shapeless中,coproducts基本上可以看作是一个"Either with any number of possibilities rather than just two",而product被实现为一个异构列表,意思是"a collection of any number of values which can also be of varying types".

阅读更多关于产品的信息(又名 "heterogenous lists")here and about coproducts (aka "discriminated unions") here