一个 Haskell 类型构造器仅仅是一个函数吗?

9

我正在学习《Haskell编程原理》这本书,其中有一道练习要求判断以下代码 [稍做修改] 是否合法:

module Test where

type Subject = String
type Verb = String
type Object = String

data Sentence = 
  Sentence Subject Verb Object
  deriving (Eq, Show)

a1 = Sentence "I" "like" "cheese"
a2 = Sentence "I" "scream"

我的初衷是代码会失败,因为在a2的定义中,Sentence只有两个参数。但发现 GHCi 能够成功加载该模块。我进行了一些实验,发现我能够输入以下命令:

a3 = a2 "icecream"

如果在GHCi中输入a3,将会打印Sentence "I" "scream" "icecream"。而如果我查询a2的类型,则会得到a2 :: Object -> Sentence。因此,如果我理解正确的话,a2的行为就像是一个部分应用的函数。

因此问题是:在所有情况下,类型构造器是否真的只是一个函数(返回类型值)- 与普通函数有所区别,只是它必须以大写字符开头?


4
施工部分中的一部分是“是”的-但您也可以将其用于模式匹配,在那里它当然不再是一个函数;) (注:原文语法有些问题,我在翻译时做了少量调整以确保句子通顺) - Random Dev
2
是的,从你所描述的意义上来说,它是一个函数。你可以通过在ghci中键入:t Just来进一步确认这一点。 - michid
@Carsten 我还没有深入研究过模式匹配,但据我所知,我们可以在定义函数(与函数有关)和定义类实例(与类型有关)时都使用模式匹配。您能否进一步解释或为我提供有关它们在模式匹配方面的区别的参考资料?谢谢。 - Penguino
@michid 那么它不是一个函数的意义在哪里,或者说我能对类型构造函数做些什么与函数相同? - Penguino
1
如果你执行 case mySentence of (Sentence s v o) -> ...,例如 - 这里 Sentence 用于模式匹配,你不能在那里插入一个函数(好吧,有扩展...但在基本层面上你不能)。 - Random Dev
显示剩余2条评论
1个回答

13

首先,你在谈论的是数据构造函数,而不是类型构造函数。该示例恰好包含了一个(零元)类型构造函数 Sentence 和一个三元数据构造函数 Sentence。为了清楚起见,请区分它们:

data SentenceTC = SentenceDC Subject Verb Object

SentenceTC是一个类型构造器,SentenceDC是一个数据构造器。

那么问题是:

SentenceDC只是一个函数吗?

答案是,它一个函数,但不是“仅仅”是一个函数。它具体是一个可逆函数,即每个参数组合都会得到不同的结果。因此,总是可以从生成的SentenceTC值推断出它所使用的参数。这也是你在模式匹配构造器时发生的事情。

a1Verb :: Verb
a1Verb = case a1 of
    Sentence _ v _ -> v

使用一般函数,例如

,这是不可能实现的。
n' :: Int
n' = abs n
 where n = -3

nNew :: Int
nNew = case n' of
   abs n -> n   -- error, `abs` can not be used as a pattern match

这也不合理,因为有两个不同的数字的 abs 值都等于 n' (即 -33)。

但是,SentenceDC 是一个函数,你可以像其他类型为 String -> String -> String -> SentenceTC 的函数一样使用它。反过来则不行:并非所有的通用函数都能像数据构造函数一样使用。


值得澄清的是,作为一个单射函数并不是你可以进行模式匹配的唯一原因。也许数据构造器是一种可以创建值而不仅仅是返回值的函数? - chepner
3
@chepner,我认为最好将构造函数看作至少两个独立的部分:一个用于构建值的函数和一个用于在其上匹配的模式。你获得哪个取决于它出现的语法位置。 - dfeuer
它还具有满射性,也就是说,对于SentenceTC类型的每个值,都可以通过某些参数由SentenceDC返回。 - Alexey Romanov
1
在这种情况下是的@AlexeyRomanov(当然忽略 ⊥),但这是因为示例中只有一个构造函数。一般来说,构造函数不是满射的。 - leftaroundabout

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