Haskell 什么是数据。。。你说哈斯克尔在哪里?

Haskell 什么是数据。。。你说哈斯克尔在哪里?,haskell,syntax,gadt,Haskell,Syntax,Gadt,我在以下网站看到了这个片段: 数据是什么。。。你的意思是什么?我认为关键字data用于定义一个新类型。它定义了一个新类型,语法被调用 它比普通语法更通用。您可以使用GADT编写任何常规类型定义(ADT): data E a = A a | B Integer 可以写为: data E a where A :: a -> E a B :: Integer -> E a 但您也可以限制右侧的内容: data E a where A :: a -> E a B :

我在以下网站看到了这个片段:


数据是什么。。。你的意思是什么?我认为关键字
data
用于定义一个新类型。

它定义了一个新类型,语法被调用

它比普通语法更通用。您可以使用GADT编写任何常规类型定义(ADT):

data E a = A a | B Integer
可以写为:

data E a where
  A :: a -> E a
  B :: Integer -> E a
但您也可以限制右侧的内容:

data E a where
  A :: a -> E a
  B :: Integer -> E a
  C :: Bool -> E Bool
这在正常的ADT声明中是不可能的

有关更多信息,请查看Haskell wiki或


原因是类型安全
ExecutionAST t
应该是返回
t
的语句类型。如果你写一个普通的ADT

data ExecutionAST result = Return result 
                         | WriteRegister M_Register Word8
                         | ReadRegister M_Register
                         | ReadMemory Word16
                         | WriteMemory Word16
                         | ...
然后,
ReadMemory 5
将是类型为
ExecutionAST t
的多态值,而不是单态的
ExecutionAST Word8
,这将进行类型检查:

x :: M_Register2
x = ...

a = Bind (ReadMemory 1) (WriteRegister2 x)
该语句应从位置1读取内存并写入寄存器
x
。然而,从内存中读取会产生8位单词,而写入
x
则需要16位单词。通过使用GADT,您可以确保它不会编译。编译时错误比运行时错误好

GADT还包括。如果您试图以这种方式编写绑定:

data ExecutionAST result = ... 
                           | Bind (ExecutionAST oldres)
                                  (oldres -> ExecutionAST result)
那么它将不会编译,因为“oldres”不在范围内,您必须编写:

data ExecutionAST result = ...
                           | forall oldres. Bind (ExecutionAST oldres)
                                                 (oldres -> ExecutionAST result)

如果您感到困惑,请查看链接视频中更简单的相关示例。

注意,也可以设置类约束:

data E a where
  A :: Eq b => b -> E b

更重要的是,与常规的
数据
声明不同,这实际上导致实例字典存储在类型中,允许您通过模式匹配来恢复它,就像存在类型一样。@hammar我不理解您的评论意味着什么。我不理解这样的措辞(用我的重新措辞)“通过模式匹配恢复实例字典,因为它存储在类型中”。当我进行模式匹配时,我会根据结构的形状进行解构,我不知道这是如何转化为“实例字典”的,也不知道它存储在类型中的不同之处。我应该阅读/学习什么来理解这一点?有人能解释一下,为什么这里需要GADT吗?@wliao:补充了一个解释。我发现你的解释比视频剪辑好。谢谢
data E a where
  A :: Eq b => b -> E b