Scala 相当于 Haskell 中的“data”声明

heg*_*ash 3 haskell functional-programming scala

我正在尝试以函数式风格编写 Scala 代码,并且想要创建一个自定义类型,例如以下 Haskell 定义:

data Day = Mo | Tu | We | Th | Fr | Sa | Su
Run Code Online (Sandbox Code Playgroud)

我知道 Scala 倾向于从 Haskell 借用一些东西,所以想知道这种声明在 Scala 中是否可能。

Ami*_*Mal 7

我不太了解 Haskell,但我只是快速浏览了一下,看起来数据声明有点像ADT(代数数据类型),给出了 haskell 网站中的这个示例:

 data Maybe a = Just a | Nothing
Run Code Online (Sandbox Code Playgroud)

与 Scala 中 Haskell 的数据类型类似的概念MaybeOption,它表示一个值存在的可能性:

sealed trait Option[+A] { /* some methods */ }
final case class Some[+T](value: T) extends Option[T] { /* some methods */ }
case object None extends Option[Nothing] { /* some methods */ }
Run Code Online (Sandbox Code Playgroud)

在 Scala 中,这些类型的数据类型几乎总是由密封特征(即产品类型)和一些子类型/对象(主要称为求和类型)表示(在本例中),SomeNoneHaskell 中非常相似(JustNothing)。

现在,在您的情况下,您的数据不需要这些构造函数,因此您可以将 is 表示为枚举,或者只使用 ADT:

// using ADT

// define product type
sealed trait Day

// define sum types
case object Mo extends Day
case object Tu extends Day
case object We extends Day
case object Th extends Day
case object Fr extends Day
case object Sa extends Day
case object Su extends Day
Run Code Online (Sandbox Code Playgroud)

Scala 2 枚举(一般不推荐,但可以工作):

object Day extends Enumeration {
  type Day = Value
  val Mo, Tu, We, Th, Fr, Sa, Su = Value
}
Run Code Online (Sandbox Code Playgroud)

或者 Scala3 枚举(如果您使用 Scala3,这是您的最佳选择):

enum Day:
  case Mo, Tu, We, Th, Fr, Sa, Su
Run Code Online (Sandbox Code Playgroud)

  • @ThomasM.DuBuisson:这不是 Scala 特有的。“经典”OO 语言没有代数和类型,但可以使用继承来模拟它们:和类型成为类,数据构造函数成为子类。这就是它在任何类似 Smalltalk/Simula 的 OO 语言中的工作方式,也是它在 Scala 中的工作方式。然而,从 Scala 3 开始,以 [*Enumerations*](https://docs.scala-lang.org/scala3/reference/enums/adts.html) 的形式原生支持 (G)ADT。Scala 3 的等价物是 `enum Option[+T] { case Some(value: T); 案例 无 }` (5认同)
  • @ThomasM.DuBuisson 还请记住,Scala 的设计目标之一(至少最初是,多年来没有看过它)是与 Java 的双向互操作。这意味着任何可以用 Scala 表达的东西都需要简单的规则来决定如何从 Java 端看到它。在 JVM 中表示 sum-types 之类的最直接的方法是使用子类。因此,Scala 的原始语法甚至不是真正“瞄准”总和类型的直接编码,而是使用子类来实现总和类型目的的简单语法。 (2认同)