And*_*rew 17 haskell scala algebraic-data-types
在Scala中,我可以描述这样的ADT:
sealed trait Foo
case class A(a: Int) extends Foo
case class B(b: String) extends Foo
case class C(a: A, b: B) extends Foo
Run Code Online (Sandbox Code Playgroud)
如何在Haskell中做同样的事情?
data Foo = A Int | B String | C A B
Run Code Online (Sandbox Code Playgroud)
这是行不通的,因为A和B不是类型。我应该使用GHC扩展名吗?
chi*_*chi 26
在Scala中,你的ADT品牌A,B,C要的亚型Foo。在Haskell我们没有亚型,因此A,B,C是代替型的构造Foo。
一些可能的解决方法:
重复这些字段。这是最基本的选择。
data Foo = A Int | B String | C Int String
Run Code Online (Sandbox Code Playgroud)定义其他类型,以便我们可以多次重用它们。
data AT = AT Int -- can have many arguments
data BT = BT String -- can have many arguments
data Foo = A AT | B BT | C AT BT
Run Code Online (Sandbox Code Playgroud)利用GADT
data FooTag = AT | BT | CT
data Foo (tag :: FooTag) where
A :: Int -> Foo 'AT
B :: String -> Foo 'BT
C :: Foo 'AT -> Foo 'BT -> Foo 'CT
Run Code Online (Sandbox Code Playgroud)
在这里,在最后一行中,我们可以A使用type 引用“使用” 构造的值Foo 'AT,因为tag AT仅由构造器使用A。请注意,这种方法在上添加了一个tag参数Foo,因此它会稍微改变接口:我们不再可以编写bar :: Foo -> ...,而必须编写bar :: Foo t -> ...(或使用存在性类型)。
| 归档时间: |
|
| 查看次数: |
501 次 |
| 最近记录: |