Haskell应用程序还是节? [英] Haskell application, or section?

查看:91
本文介绍了Haskell应用程序还是节?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想翻转列表构造函数的用法,使其具有类型:

I wanted to flip a list constructor usage, to have type:

[a] -> a -> [a]

(可折叠使用),因此尝试过:

(for use in a fold), so tried:

(flip :)

但是它给出了类型:

Prelude> :t (flip :)
(flip :) :: [(a -> b -> c) -> b -> a -> c] -> [(a -> b -> c) -> b -> a -> c]

这让我感到惊讶,但是似乎这被解析为(:)的左部分,而不是部分地应用了flip.使用翻页将其重写为infix似乎可以解决这个问题,

This surprised me, but it appears that this was parsed as a left section of (:), instead of a partial application of flip. Rewriting it using flip as infix seems to overcome this,

Prelude> :t ((:) `flip`)
((:) `flip`) :: [a] -> a -> [a]

但是我找不到定义此行为的规则,我认为函数应用程序是最高优先级,并且被评估为从左到右,所以我希望这两种形式是等效的.

But I couldn't find the rule defining this behavior, and I thought that function application was the highest precedence, and was evaluated left->right, so I would have expected these two forms to be equivalent.

推荐答案

正在将:放在括号中,这使您的第二个示例起作用,而不在flip周围使用反引号.

It was putting : in parentheses that made your second example work, not using backticks around flip.

我们经常说功能应用程序具有最高优先级"来强调例如f x + 1应该读为(f x) + 1,而不是f (x + 1).但这并不是完全准确的.如果它是(flip :),并且按您的预期进行了解析,则(f x) + 1之后的最高优先级将是(f x)+的应用;否则,则为(f x).整个表达式f x + 1最终将被解析为f应用于三个参数:x+1.但这会发生在所有涉及中缀运算符的表达式中!甚至将简单的1 + 1都识别为应用于+11(然后抱怨缺少的Num实例将允许1作为函数).

We often say that "function application has highest precedence" to emphasise that e.g. f x + 1 should be read as (f x) + 1, and not as f (x + 1). But this isn't really wholly accurate. If it was, and (flip :) parsed as you expected, then the highest precedence after (f x) + 1 would be the application of (f x) to +; the whole expression f x + 1 would end up being parsed as f applied to 3 arguments: x, +, and 1. But this would happen with all expressions involving infix operators! Even a simple 1 + 1 would be recognised as 1 applied to + and 1 (and then complain about the missing Num instance that would allow 1 to be a function).

从本质上说,对功能应用程序具有最高优先级"的这种严格理解将意味着功能应用程序将是有史以来的一切. infix运算符总是以某些函数的参数结尾,而从不实际用作infix运算符.

Essentially this strict understanding of "function application has highest precedence" would mean that function application would be all that ever happens; infix operators would always end up as arguments to some function, never actually working as infix operators.

实际上,优先级(和关联性)是解决涉及多个中缀运算符的表达模棱两可的机制.函数应用程序不是中缀运算符,并且根本不参与优先级/关联性系统.不调用运算符的术语链会在调用功能应用程序之前进行优先级解析来解析操作员应用程序(因此称为最高优先级"),但不是真正的优先级会导致它.

Actually precedence (and associativity) are mechanisms for resolving the ambiguity of expressions involving multiple infix operators. Function application is not an infix operator, and simply doesn't take part in the precedence/associativity system. Chains of terms that don't involve operators are resolved as function application before precedence is invoked to resolve the operator applications (hence "highest precedence"), but it's not really precedence that causes it.

这是它的工作方式.您从术语和运算符的线性序列开始;没有结构,它们只是彼此相邻地写.

Here's how it works. You start with a linear sequence of terms and operators; there's no structure, they were simply written next to each other.

我在这里所说的术语"可以是像flip这样的非运算符标识符;或字符串,字符或数字文字;或列表表达式;或带括号的子表达式;就这个过程而言,它们都是不透明的;我们只知道(并且只需要知道)它们不是中缀运算符.我们总是可以告诉运算符,因为它要么是符号"标识符,如++!@>,要么是反引号中的字母数字标识符.

What I'm calling a "term" here can be a non-operator identifier like flip; or a string, character, or numeric literal; or a list expression; or a parenthesised subexpression; etc. They're all opaque as far as this process is concerned; we only know (and only need to know) that they're not infix operators. We can always tell an operator because it will either be a "symbolic" identifier like ++!@>, or an alphanumeric identifier in backticks.

因此,术语和运算符的顺序.您会在一行中找到所有不包含运算符的一个或多个术语的所有链.每个这样的链都是功能应用程序的链,并且成为一个术语. 1

So, sequence of terms and operators. You find all chains of one or more terms in a row that contain no operators. Each such chain is a chain of function applications, and becomes a single term.1

现在,如果两个操作符彼此紧邻,则会出现错误.如果您的序列以运算符开头或结尾,那也是一个错误(除非这是运算符部分).

Now if you have two operators directly next to each other you've got an error. If your sequence starts or ends in an operator, that's also an error (unless this is an operator section).

在这一点上,您可以确保拥有一个严格交替的序列,例如术语算子术语,算子术语算子术语等.因此,请选择优先级最高的算子以及其左侧和右侧的术语,并称其为算子申请,这三个项目成为一个术语.当您有多个具有相同优先级的运算符时,关联性便是平局.漂洗并重复直到整个表达式变成一个单项(或关联性无法打破平局,这也是一个错误).这意味着在涉及运算符的表达式中,顶级应用程序"总是 运算符之一,而不是普通的函数应用程序.

At this point you're guaranteed to have a strictly alternating sequence like term operator term operator term operator term, etc. So you pick the operator with the highest precedence together with the terms to its left and right, call that an operator application, and those three items become a single term. Associativity acts as a tie break when you have multiple operators with the same precedence. Rinse and repeat until the whole expression has become a single term (or associativity fails to break a tie, which is also an error). This means that in an expression involving operators, the "top level application" is always one of the operators, never ordinary function application.

其结果是,在没有任何情况的情况下,运算符最终可能会作为参数传递给函数.根本不可能.这就是为什么我们需要(:)语法来禁用运算符的运算符性质",并以其身份作为值的原因.

A consequence of this is that there are no circumstances under which an operator can end up passed as the argument to a function. It's simply impossible. This is why we need the (:) syntax to disable the "operator-ness" of operators, and get at their identity as values.

对于flip :,唯一的非运算符术语链只是flip,因此没有普通的函数应用程序可用于最高优先级"解析. :然后去寻找它的左右参数(但这是一个小节,所以没有右参数),并在它的左边找到flip.

For flip : the only chain of non-operator terms is just flip, so there's no ordinary function application to resolve "at highest precedence". : then goes looking for its left and right arguments (but this is a section, so there's no right argument), and finds flipon its left.

要使flip接收:作为参数而不是相反,必须编写flip (:). (:)不是运算符(用括号括起来,所以里面没有关系),因此我们有两个没有运算符的项,因此可以通过将flip应用于(:).

To make flip receive : as an argument instead of the other way around, you must write flip (:). (:) is not an operator (it's in parentheses, so it doesn't matter what's inside), and so we have a chain of two terms with no operators, so that gets resolved to a single expression by applying flip to (:).

1 另一种查看方式是,您可以识别所有没有用运算符分隔的术语序列,并在它们之间插入函数应用程序运算符".此运算符"的优先级高于可能分配给其他运算符的优先级,并且是左关联的.然后,运算符解析逻辑将按照我所描述的方式自动处理函数应用程序.

1 The other way to look at this is that you identify all sequences of terms not otherwise separated by operators and insert the "function application operator" between them. This "operator" has higher precedence than it's possible to assign to other operators and is left-associative. Then the operator-resolution logic will automatically treat function application the way I've been describing.

这篇关于Haskell应用程序还是节?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆