Haskell 奇怪的波浪形语法

Haskell 奇怪的波浪形语法,haskell,Haskell,GHC接受这段代码,但它应该是非法语法(?)对发生了什么有任何猜测吗 module Tilde where ~ x = x + 2 -- huh? ~ x +++ y = y * 3 -- this makes sense (+++)等式很有意义:它声明了一个操作符,使用中缀语法,并在第一个参数上使用了一个无可辩驳的模式匹配 第一个“方程式”看起来与开始时一样。但是没有接线员。如果我问 λ> :i ~ ===> <interactiv

GHC接受这段代码,但它应该是非法语法(?)对发生了什么有任何猜测吗

module Tilde  where

~ x = x + 2             -- huh?

~ x +++ y = y * 3       -- this makes sense
(+++)
等式很有意义:它声明了一个操作符,使用中缀语法,并在第一个参数上使用了一个无可辩驳的模式匹配

第一个“方程式”看起来与开始时一样。但是没有接线员。如果我问

λ> :i ~
===> <interactive>:1:1: error: parse error on input `~'

λ> :i (~)
===> class (a ~ b) => (~) (a :: k) (b :: k)
     -- Defined in `Data.Type.Equality'
     instance [incoherent] forall k (a :: k) (b :: k). (a ~ b) => a ~ b
     -- Defined in `Data.Type.Equality'
并尝试永远运行
x
循环。因此,奇怪实际上是定义

x = x + 2

那么,
~
在做什么?

波浪形图案正是在做它在另一个例子中所做的事情:它使图案无可辩驳(因此图案匹配不能失败)。当然,在这两种情况下(作为一个普通变量,总是匹配的),这种模式已经是无可辩驳的,但这并不意味着平铺是非法的,只是没有必要

x = 5
创建名为
x
的全局变量,该变量绑定到值
5
。添加瓷砖使图案匹配无可辩驳,但它已经无可辩驳,所以这没有多大意义。但是写这样的东西是合法的

(xs, ys) = span odd [1..10]
这定义了两个全局变量,
xs
ys
,其中包含1到10之间的所有奇数和所有偶数。如果你愿意的话,你甚至可以通过添加一个波浪来让这一点变得无可辩驳。当然,这种模式不会失败(如果表达式类型正确),所以这没有意义。但请考虑:

~(x:xs) = filter odd [1..10]
如果过滤器返回至少一个结果,则定义两个全局变量,
x
xs
。如果过滤器返回零结果,则模式匹配将失败。(实际上,这意味着访问
x
xs
将引发模式匹配失败异常。)

你甚至可以写一些非常奇怪的东西,比如

False = True

这个看似无意义的声明模式将模式
False
与值
True
相匹配,并且两种方式都不起作用。这是语言中一个晦涩难懂的角落。

x
是一个幂零函数,那么什么(无可辩驳地)与什么匹配呢?例如,我不能编写等效的lambda表达式。@AntC它根本不是一个函数,正如您所观察到的,它是一个
整数。你绝对不能写一个等价的lambda表达式;所有lambda表达式都是函数。模式
x
匹配任何
Integer
,将
Integer
绑定到名称
x
;因此,在
~x=x+2
中,名称
x
绑定到表达式
x+2
。@AntC类似于“niladic函数”的概念对Haskell来说是陌生的。在Haskell中,所有函数只接受一个参数。@AntC
let
bindings要么是模式绑定,要么是函数绑定(如果它有一些参数)。当没有参数时,它是一种模式,或者是简单的单变量模式(已经无可辩驳),或者是更复杂的模式,如
(a,b)=(1,2)
(x:xs)=[1..]
~(x:xs)=[]
@AntC,见报告。(…但是顶级绑定已经是无可辩驳的,所以即使在您的示例中,
~
也完全没有必要。)@DanielWagner真的吗?有趣…我不知道。如果他们不知道,他们应该在什么时候失败@MathematicalOrchid@luqui当你第一次尝试使用绑定时,我想…嗯,但只有当它们是无可辩驳的时,这才有效…我明白你的意思。好吧,如果我想给出一个等式,将
~
定义为(一元,前缀)运算符,这将是
(~)x=x+2
;-)
False = True