【问题标题】:Is a Haskell type constructor 'just' a function?Haskell 类型的构造函数“只是”一个函数吗?
【发布时间】:2021-05-26 09:49:22
【问题描述】:

我正在阅读“Haskell Programming from first principle”,并找到了一个练习,询问以下 [此处稍微编辑的代码] 是否有效:

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 的行为就像一个部分应用的函数。

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

【问题讨论】:

  • (构造部分)的一部分 是的 - 但您也可以将它们用于模式匹配,当然它不再是一个函数;)
  • 这是一个你描述是的意义上的功能。您可以通过例如进一步确认这一点在 ghci 中输入 :t Just
  • @Carsten 我还没有在模式匹配方面做很多事情,但据我所知,我们可以在定义函数时进行模式匹配(与函数有关)以及何时定义一个类实例(与类型有关)。您能否进一步解释或给我一个参考,说明它们在模式匹配方面有何不同?谢谢
  • @michid 那么有什么意义它是 not 函数,或者我可以对类型构造函数做任何我可以对函数做的事情吗?
  • 好吧,如果你这样做 case mySentence of (Sentence s v o) -> ... 例如 - 这里 Sentence 用于模式匹配,你不能在那里插入函数(当然有扩展......但在基本层面上你不能)

标签: function haskell types algebraic-data-types custom-data-type


【解决方案1】:

首先,您在这里谈论的是数据构造函数,而不是类型构造函数。该示例恰好包含(空)类型构造函数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 类型的其他函数做的事情。但并非相反:并非所有可以使用数据构造函数执行的操作也可以使用相同类型的通用函数完成。

【讨论】:

  • 可能值得澄清的是,作为单射函数并不是您可以进行模式匹配的唯一原因。也许数据构造函数是一个可以创建一个值的函数,而不仅仅是返回一个值?
  • @chepner,我认为最好将构造函数视为至少两个独立的东西:构造值的函数和匹配它们的模式。你得到哪个在语法上由它出现的位置决定。
  • 它也是满射的,因为 SentenceTC 类型的每个值都由 SentenceDC 返回某些参数。
  • @AlexeyRomanov 在这种情况下是的(当然忽略⊥),但那是因为示例中只有一个构造函数。一般来说,构造函数不是满射的。
猜你喜欢
  • 2013-08-14
  • 1970-01-01
  • 2016-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-07
相关资源
最近更新 更多