使用密封的 case 对象实现枚举类型(从 Haskell 到 Scala)

3

我希望你能帮忙将一些Haskell代码翻译成Scala语言。 在Haskell中,我实现了一个枚举类型,如下所示:

data Rank = Jack | Queen | King | Ace | Num Int deriving (Show, Eq) 

我希望使用sealed case Objects在scala中实现它。

sealed trait Rank
case object Jack extends Rank
case object Queen extends Rank
case object King extends Rank
case object Ace extends Rank
case object Num Int extends Rank

当使用 Num Int 类型时,我遇到了一个错误。我认为它应该写成一个单词!有什么帮助吗!


可能是Scala:类型类和ADT之间的区别?的重复。 - Shoe
1
@Shoe:我认为这不能算是 https://dev59.com/lGIk5IYBdhLWcg3wqPoi 的重复,因为 OP 的问题根本不涉及类型类。 - Régis Jean-Gilles
@RégisJean-Gilles,那个问题中找到的答案代表了Haskell和Scala形式中的ADT和类型类,这正是这个问题所关注的。 - Shoe
我猜这是有争议的,但考虑到另一个问题的广泛性,以及这个问题的特定性,我认为这不是重复的好选择。毫无疑问,另一个问题是相关的,无论如何都值得SaKou一读。 - Régis Jean-Gilles
1个回答

5
在Haskell中,`Num`是一个类,需要一个类型参数,比如`Int`,才能产生像`Num Int`这样的约束。因此,在Scala中,你应该期望类似于以下内容:
case class Num(value: Int) extends Rank

请注意,与Haskell不同,Scala要求您给参数命名。
此外,在Scala代码中,您缺少为Rank定义的Show和Eq实例,但这似乎不是问题的一部分。

请注意,在这种情况下应该是一个“密封的case class”,否则将会打开“Rank”特质的密封。 (相比之下,“object”天生就是密封的。) - Madoc
@Madoc 谢谢,这是一个好的提示,但并不总是需要 - 所以我不会修复我的答案。通常为枚举使用 sealed 是为了让编译器生成 match may not be exhaustive 检查,并且即使它不是 sealed,对于 case class 仍然可以正常工作,因为在 Scala 中禁止了 case-to-case 继承,而编译器不会担心类到 case 的继承(它不影响检查)。但如果您有其他原因来封闭您的类型系统,这个提示仍然适用。 - Archeg
@dfeuer 谢谢,我对 Haskell 术语不是很熟悉。我已经修复了,看起来还可以吗? - Archeg
1
我想指出包含的Haskell代码,即data Rank = ... | Num Int定义了一个新的名称Num,与标准的Prelude.Num无关,它是一个数据构造器而不是类型类。因此,虽然我不知道足够的Scala来确定,但我怀疑这个答案可能基于对Haskell代码的误解,而不是完全正确的。 - Daniel Wagner
1
@DanielWagner 我知道这一点,我在Scala中也定义了Num,它与Haskell的Prelude.Num无关。然而,我的措辞或Haskell术语可能不正确,因为我主要是Scala开发人员,只了解一些Haskell(大多数是实践方面),所以如果我说错了什么,请纠正我。 - Archeg
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接