Haskell 类型构造函数“只是”一个函数吗?

问题描述

我正在学习“Haskell Programming from first原则”并发现了一个练习,询问以下[此处稍微编辑的代码]是否有效:

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 的行为与部分应用的函数完全一样。

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

解决方法

首先,您在这里谈论的是数据构造函数,而不是类型构造函数。该示例恰好包含(空)类型构造函数 Sentence 和三元数据构造函数 Sentence。明确哪个是哪个:

data SentenceTC = SentenceDC Subject Verb Object

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

所以,问题是:

SentenceDC 只是一个函数吗?

答案是,它一个函数,而不是“只是”一个函数。它特别是一个 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 类型的函数做的事情。但反过来也一样:并非您可以使用数据构造函数执行的所有操作也可以使用相同类型的通用函数来完成。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...