在Haskell中键入模式和泛型类

时间:2010-03-12 15:38:50

标签: generics reflection haskell

我正在尝试理解Haskell中的类型模式和泛型类,但似乎无法理解它。

有人可以用外行的方式来解释吗?

[1]中,我已经阅读了

  

“为了将函数统一应用于所有数据类型,我们以统一的方式查看数据类型:除了基本的预定义类型(如Float,IO和→)之外,每个Haskell数据类型都可以被视为可能已标记的标记总和产品。“

然后提到Unit:*::+:。 Haskell中的所有数据类型都是上面提到的自动版本,如果是这样的话,我如何根据:*:等来确定特定数据类型的表示方式? haskell.org上泛型类(ch.7.16)的用户指南没有提到预定义类型,但是如果类型模式应该是详尽的,那么它们不应该在每个函数中处理吗?

  

[1]比较Haskell,Ralf Hinze,Johan Jeuring和AndresLöh的泛型编程方法

2 个答案:

答案 0 :(得分:4)

他们是手工做的。它类似于布尔代数中使用的“产品总和”形式。由于每个代数数据类型都是由和和产品构成的,因此转换可能与布尔代数非常相似,只是在这种情况下它们提取结构并丢弃一些语义。

他们的示例是List a,最初定义为

data List a = Nil | Cons a (List a)

但转变为

data List a = Unit :+: (a :*: (List a)).

我只是略读了论文,但是我可以看到从声明中提取类型构造函数并从+*运算符中构建所有内容的一些价值。

在他们使用这些更通用的结构类型之前,他们定义了一个同构,以表明它们确实是相同的。它们还包括带有记录和构造函数名称的标记,我将不再使用它们:

from Nil = Unit
from (Cons x y) = x :*: y
to Unit = Nil
to (x :*: y) = Cons x y

答案 1 :(得分:1)

好的,你可能不喜欢听到这个,但你需要听到它。 这是一篇研究论文。这不是关于如何完成它的说明手册或备忘单。这是如何以一种新形式进行的具体探索,该形式使用了Haskell已经为您提供的内容(即,它不是标准库......但是......这是一种制作方式,一次,所以你不需要稍后重新做。)

就像你编写代码来创建堆栈或队列一样 - 这是一个练习。如果你可以将它用于真实的东西,那么你就会有更多的力量,但总的来说,它只是一个例证,或者你可以用语言做什么,而不是指导你如何去做。

这并不是说这篇论文只是一个玩具练习,并且永远不能用于任何重要的事情,只是他们的观点是展示你如何组织你的程序,这样你就不会写出那么多的样板,或者重复自己而不费力。

对于{| ... |}(...)的东西,这是作者谈论类型和该类型值的方式。具体来说,{|...|}是作者将类型表示为值的一种方式。这只是挥手悬浮的怀疑思想实验。这是演奏“让我们假装”的复杂方式。作者说,“看,Haskell不会真的允许我们将一个类型传递给一个函数,所以我们将使用这个形式作为一种速记方式来表达,”记住整个我们刚刚介绍的部分,展示了如何使用所有Con(结构)和Label类型来表示类型?好吧假装我们这样做了,某些类型a的结果就是我们所说的{|a|}。“这是一个表示函数(编码,解码,映射,showP等等)的符号。 )获取并使用某个术语的类型和值。

关于你的其他问题:

  1. 不会所有模式匹配 如果我开始重新定义,List就会中断 List? 如果你以不再符合其“当前”定义的方式重新定义它,那么它当然会! (提示:这是{|...|}形式的要点:你的函数知道你正在玩什么类型,所以它也知道如何玩它!;)

  2. 甚至可以重新定义数据 类型? 当然如此! (我觉得像#haskell @FAQ回答者,在这里......)见上面的提示。 :)

  3. 我希望能回答你的问题。如果您有更多问题,或者想要与现场人员一起散列,您可以随时通过freenode上的IRC频道(以防万一你不知道为什么我把那个哈希标记和'at'符号放在上面的句子)。 非常友好,乐于助人的人们,到处都是巨魔的沮丧! :)