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'
(即 -3
和 3
) .
但是,是的,SentenceDC
是一个函数,您可以用它来做任何您可以用其他 String -> String -> String -> SentenceTC
类型的函数做的事情。但不是相反:不是所有你可以用数据构造函数做的事情也可以用相同类型的通用函数来完成。
我正在学习 "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'
(即 -3
和 3
) .
但是,是的,SentenceDC
是一个函数,您可以用它来做任何您可以用其他 String -> String -> String -> SentenceTC
类型的函数做的事情。但不是相反:不是所有你可以用数据构造函数做的事情也可以用相同类型的通用函数来完成。