【问题标题】:Why cannot one define := in GHC?为什么不能在 GHC 中定义 :=?
【发布时间】:2014-02-08 02:38:57
【问题描述】:

为什么不能在 GHC 中定义运算符 :=?在未来的版本中可以消除此限制吗?

这是输出:

[1 of 1] Compiling Images           ( Images.hs, interpreted )

Images.hs:19:1:
    Invalid type signature: (:=) :: HasSetter s => s a -> a -> IO ()
    Should be of form <variable> :: <type>

【问题讨论】:

  • : 开头的名称保留给数据类型命名空间:data (:=) a b = (:=) a b
  • @danbst,Haskell 通常不允许类型/数据构造函数和函数具有相同的名称格式。例如,类型/数据构造函数必须以大写(或:)开头,函数名称必须以小写(或有效的值级运算符字符)开头。不过,您可以使用 .==: 作为中缀函数名。
  • 从本质上讲,冒号是“大写”,用于命名规则。
  • @danbst 函数空间和数据构造函数空间绝对重叠。所有数据构造函数都是函数。 Haskell 指定模式匹配的方式需要能够在语法上区分数据构造函数和其他值。
  • @jcarpenter 您可以在运算符中使用冒号,但不能在开头使用。例如,(=:) = () 是一个有效的定义。

标签: haskell


【解决方案1】:

构造函数与函数

构造函数根据旧数据创建新数据类型。让我们推出自己的清单:

data List a = Empty | Cons a (List a)

myList = Const 1 (Cons 2 Empty) -- 1:2:[] =[1,2]

uncons x' (Cons x xs) = if x == x' then xs else Cons x xs

这里,Cons :: a -&gt; List a 是一个特殊函数,它接受一个元素和一个列表,并生成一个更长的列表。

重要的是构造函数和普通函数之间存在区别,以便编译器知道在模式匹配中哪个是有效的:

headM (Cons x xs) = Just x
headM Empty = Nothing

这是有道理的,但这没有:

previousHead (uncons x xs) = Just x
previousHead xs = Nothing

因为计算机如何知道您删除了哪个元素或者您是否确实删除了一个元素?

中缀构造函数和函数

有时,与列表一样,让构造函数工作中缀会很有帮助,因此我们实际上有等价于

data [a] = [] | a:[a]

所以我们可以编写像1:2:[] 这样的列表。

中缀函数需要与标识符分开,这样我们就可以明确地写出x:xs 而没有空格,所以中缀函数(包括像: 这样的中缀构造函数必须完全由符号组成,而不是字母。

编译器仍然需要能够将构造函数与普通函数区分开来,因此我们需要构造函数以大写开头的规则。语言设计者将:指定为唯一的大写符号,所以中缀构造函数必须以它开头,而普通函数则不能。

你可以做什么:=

可以使用:=作为构造函数,所以你可以定义

data Assignment a = Variable := Expression a

但是如果你想调用一个普通的函数:=,你不能,因为:不能放在前面,因为它算作大写符号,你必须从别的开始,对于(简单但毫无意义的)示例:

(.:=) :: Maybe a -> a -> Maybe a
Nothing .:= x   = Just x
Just y  .:= x   = Just x

【讨论】:

    猜你喜欢
    • 2020-09-23
    • 1970-01-01
    • 2017-07-14
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多