Haskell 类型构造函数 'just' 是一个函数吗?

Is a Haskell type constructor 'just' a function?

我正在学习 "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"

a3(输入GHCi)会打印出Sentence "I" "scream" "icecream"。另外,如果我查询 a2 的类型,我会得到 a2 :: Object -> Sentence。因此,如果我理解正确,a2 的行为与部分应用的函数完全一样。

因此问题是:在所有情况下,类型构造函数真的只是一个函数(returns 一个类型值)- 与 'normal' 函数的区别仅在于它必须以一个大写字符?

首先,你在这里谈论的是数据构造函数,而不是类型构造函数。该示例恰好包含一个(零)类型构造函数 Sentence 和一个三元数据构造函数 Sentence。为了弄清楚哪个是哪个:

data SentenceTC = SentenceDC Subject Verb Object

SentenceTC是类型构造函数,SentenceDC是数据构造函数。

所以,问题是:

Is SentenceDC just a function?

答案是,它一个函数,但“不仅仅是”一个函数。它特别是一个 injective function,即参数的每个组合都会导致不同的结果。因此,总是可以从结果 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 类型的函数做的事情。但不是相反:不是所有你可以用数据构造函数做的事情也可以用相同类型的通用函数来完成。