(a -> a) 和 a -> a 之间的区别一个

发布于 2024-11-05 01:44:04 字数 220 浏览 6 评论 0原文

我注意到(尽管我曾经被告知 (a -> a)a -> a 表示同一件事),当我收到错误消息时我使用(a -> a)。在类型中使用括号时,我应该只使用 (a -> a) 吗? (即 (5 + 3) 而不是 5 + 3)?只是不太确定何时有必要

I've noticed that (although I was once told that (a -> a) and a -> a meant the same thing), I get error messages when I use the (a -> a). Should I only use (a -> a) when using brackets amongst the types? (i.e. (5 + 3) instead of 5 + 3)? Just not quite certain of when it's necessary

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

生寂 2024-11-12 01:44:04

(a -> a)a -> a 单独使用时是相同的,

ff :: (a -> a)   -- this compiles
ff = id

gg :: a -> a
gg = id

h :: a -> a -> Bool
h _ _ = True

i = h ff gg   -- this compiles => ff & gg are of the same type.

但与更多类型组合时会有所不同,例如:

 a -> a  -> b
(a -> a) -> b

这是因为 -> 是右关联的,所以 一个->一个-> b 实际上意味着 a -> (a -> b) (获取一个 a 并返回一个函数),这与 (a -> a) ->; b(接受一个函数并返回b)。

这就像(1+2)*31+2*3不同。

(a -> a) and a -> a are the same alone,

ff :: (a -> a)   -- this compiles
ff = id

gg :: a -> a
gg = id

h :: a -> a -> Bool
h _ _ = True

i = h ff gg   -- this compiles => ff & gg are of the same type.

but will be different when combined with more types like:

 a -> a  -> b
(a -> a) -> b

This is because -> is right-associative, so a -> a -> b actually means a -> (a -> b) (take an a and return a function), which is different from (a -> a) -> b (take a function and return a b).

This is like (1+2)*3 is different from 1+2*3.

我纯我任性 2024-11-12 01:44:04

当编译器可用的其他信息无济于事时,括号可以消除 Haskell 中的多个构造的歧义:

应用程序关联到左侧

因此您可以省略函数参数上的括号。

涉及中缀运算符的表达式通过运算符的固定性消除歧义。

因此,在许多情况下,具有不同固定性的二元运算符不需要括号。

具有相同优先级的连续无括号运算符必须都是左关联或右关联,以避免语法错误。

最后:

给定一个不带括号的表达式 x op y op z,必须在 x op yy op z 周围添加括号,除非某些情况关于优先级保持的条件

如果上述陈述没有任何意义, 我的一般建议:过度括号,直到您了解规则。或者,努力学习Haskell Report

Parenthesization disambiguates several constructs in Haskell, when other information available to the compiler doesn't help:

Application associates to the left

so you can omit parens on function arguments.

Expressions involving infix operators are disambiguated by the operator's fixity.

so no need for parens in many cases with binary operators of different fixity.

Consecutive unparenthesized operators with the same precedence must both be either left or right associative to avoid a syntax error.

and finally:

Given an unparenthesized expression x op y op z, parentheses must be added around either x op y or y op z, unless certain conditions about precendence hold

My general advice, if the above statements don't make any sense: over-parenthesize things, until you learn the rules. Or, study the Haskell Report very hard.

撕心裂肺的伤痛 2024-11-12 01:44:04

考虑表达式 10 / 2 / 5。这与 (10 / 2) / 510 / (2 / 5) 相同吗?如果将 / 解释为数学除法,则前者为 true,而后者为 false。所以你看,你的问题的答案是“有区别,但只是有时”。

类型则相反。 a-> b-> ca -> 相同(b -> c),并且绝对不同于 (a -> b) -> c.

你说你不太确定什么时候有必要:那就是了。当函数的参数也是一个函数时,那么它是必要的。

考虑 map :: (a -> b) -> [一]-> [b]。这与 a -> 不同。 b-> [一]-> [b],如你所见,(a -> b) 表示一种特定类型的函数:从类型 a 到类型 的函数b。

迭代 :: (a -> a) ->一个-> [a] 更有趣。该函数要求第一个参数中函数的输入和输出类型必须相同。

您可能有兴趣阅读柯里化和部分应用。众多资源中的一个很好的资源:学习 Haskell # Curried 函数

Consider the expression 10 / 2 / 5. Is that the same as (10 / 2) / 5 or 10 / (2 / 5)? If you interpret / to be mathematical division, then the former is true, while the latter is false. So you see, the answer to your question is "there is a difference, but only sometimes".

Types are the opposite. a -> b -> c is the same as a -> (b -> c), and definitely not the same as (a -> b) -> c.

You say you're not quite sure when it's necessary: well here it is. When the argument to your function is also a function, then it is necessary.

Consider map :: (a -> b) -> [a] -> [b]. This is different than a -> b -> [a] -> [b], for you see, (a -> b) indicates a specific kind of function: a function from type a to type b.

iterate :: (a -> a) -> a -> [a] is more interesting. This function requires that the input and output types of the function in the first parameter must be the same.

You may be interested in reading up on currying and partial application. One good resource among many: Learn you a Haskell # Curried Functions

娇纵 2024-11-12 01:44:04

仅当您创建高阶函数时,这才会产生影响。例如:

f :: a -> a -> b

是一个需要两个 a 类型的参数并返回一个 b 类型的值的函数,如下所示

f 2 2
f True True

但该函数

f :: (a -> a) -> b

需要一个函数作为参数。唯一一次 a ->;如果 a(a -> a) 是类型推断中唯一的参数,那么它们是相同的,就像这里的

f :: (a -> a)
-- Same type as
f :: a -> a

() in types 的规则与正常表达几乎相同。这就像更高一层的表达式。

This only makes a difference when you're making higher order functions. For example:

f :: a -> a -> b

is a function that expects two arguments of type a and return a value of type b, like so

f 2 2
f True True

But the function

f :: (a -> a) -> b

Expects a function as an argument. The only time where a -> a and (a -> a) are the same if they're the only argument in type inference, like here

f :: (a -> a)
-- Same type as
f :: a -> a

The rules for () in typing are pretty much the same as in normal expressions. It's like expressions a level above.

寂寞陪衬 2024-11-12 01:44:04

他们是一样的。您能描述一下使用 (a -> a) 时遇到的错误吗?它对我来说在 ghci-7.0.3 上工作得很好:

Prelude> let f :: (a -> a); f = id
Prelude> f "foo"
"foo"
Prelude>

一般来说,当您使用函数作为参数时,您需要在类型中使用括号。例如,map :: (a -> b) -> [一]-> [b]。如果没有括号,那就意味着别的东西。

They are the same. Could you describe the errors you get when you use (a -> a)? It works fine for me with ghci-7.0.3:

Prelude> let f :: (a -> a); f = id
Prelude> f "foo"
"foo"
Prelude>

In general, you need to use parentheses in types when you're using functions as arguments. For example, map :: (a -> b) -> [a] -> [b]. Without the parens, it would mean something else.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文