【问题标题】:Strange tilde syntax奇怪的波浪号语法
【发布时间】:2019-04-10 23:41:40
【问题描述】:

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'

这是一个令人困惑的发现,但与它无关(?)我无法定义自己的类或运算符(~) -- Illegal binding of built-in syntax,不足为奇。

哦:

λ> :i x
===> x :: Integer         -- GHCi defaulting, presumably

并试图永远运行x 循环。所以奇怪实际上是在定义

x = x + 2

~在做什么呢?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    波浪号的作用与您在另一个示例中所做的完全一样:它使模式无可辩驳(因此模式匹配不会失败)。当然,在这两种情况下,模式已经是无可辩驳的(作为一个简单的变量,总是匹配的),但这并不意味着波浪号是非法的,只是不必要的。

    【讨论】:

    • 嗯? x 是一个 niladic 函数,那么什么(无可辩驳地)与什么匹配?例如,我不能编写等效的 lambda 表达式。
    • @AntC 正如您所观察到的,这根本不是一个函数,而是一个Integer。你绝对不能写一个等价的 lambda 表达式;所有 lambda 表达式都是函数。模式x 匹配任何Integer,将Integer 绑定到名称x;所以在~x = x+2 中,名称x 绑定到表达式x+2
    • @AntC 像“niladic 函数”这样的概念对于 Haskell 来说是陌生的。在 Haskell 中,所有函数都只接受一个参数。
    • @AntC let 绑定要么是模式绑定,要么是函数绑定(如果它有一些参数)。当没有参数时,它是一个模式,可以是简单的单变量模式(已经无可辩驳),也可以是更复杂的模式,如 (a,b) = (1,2)(x:xs) = [1..]~(x:xs) = []
    • @AntC 请参阅报告中的4.4.3 Function and Pattern Bindings
    【解决方案2】:

    写作

    x = 5
    

    创建一个名为x 的全局变量,绑定到值5。添加波浪号使模式匹配无可辩驳,但它已经是无可辩驳的,所以这没有多大意义。但是写类似的东西是合法的

    (xs, ys) = span odd [1..10]
    

    这定义了两个全局变量,xsys,包含 1 到 10 之间的所有奇数和所有偶数。如果你愿意,你甚至可以通过添加波浪号来证明这一点。当然,这种模式不会失败(如果表达式类型正确),所以没有意义。但请考虑:

    ~(x:xs) = filter odd [1..10]
    

    这定义了两个全局变量xxs如果过滤器至少返回一个结果。如果过滤器返回 zero 结果,则模式匹配将失败。 (实际上,这意味着访问xxs 会引发模式匹配失败异常。)

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

    False = True
    

    这个看似荒谬的声明模式将模式False 与值True 匹配,并且没有任何作用。这是语言中那些晦涩难懂的角落之一。

    【讨论】:

    • (...但是无论如何顶级绑定已经无可辩驳,因此即使在您的示例中,~s 也是完全没有必要的。)
    • @DanielWagner 真的吗?有趣...我不知道。
    • 如果他们不是,他们应该在什么时候失败? @MathematicalOrchid
    • @luqui 当你第一次尝试使用绑定时,我想......嗯,但这只有在它们无可辩驳的情况下才有效......我明白你的意思。
    • 好的,所以如果我想给出一个方程来将~ 定义为(一元,前缀)运算符,那就是(~) x = x + 2。 ;-)
    猜你喜欢
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    • 2022-11-19
    • 2013-07-27
    • 2019-04-09
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多