为什么不能在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>
答案 0 :(得分:9)
构造函数使用旧数据创建新数据类型。让我们推出自己的清单:
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 -> 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
而不用空格,因此中缀函数(包括像:
这样的中缀构造函数必须完全由符号组成,而不是字母。
编译器仍然需要能够在构造函数为中缀时将其与普通函数区分开来,因此我们需要等效于构造函数以大写字母开头的规则。语言设计者将:
指定为唯一的大写符号,因此中缀构造函数必须从它开始,普通函数不能。{/ p>
您可以使用:=
作为构造函数,因此您可以定义
data Assignment a = Variable := Expression a
但是如果你想调用一个普通的函数:=
,你不能,因为前面不允许:
,因为它算作大写符号,你必须开始用其他东西,为(简单但毫无意义)的例子:
(.:=) :: Maybe a -> a -> Maybe a
Nothing .:= x = Just x
Just y .:= x = Just x