【问题标题】:difference between (a -> a) and a -> a(a -> a) 和 an -> a 之间的区别
【发布时间】:2011-05-03 21:26:08
【问题描述】:

我注意到(尽管有人告诉我(a -> a)a -> a 表示相同的意思),当我使用(a -> a) 时会收到错误消息。在类型中使用括号时,我应该只使用(a -> a) 吗? (即(5 + 3) 而不是5 + 3)?只是不太确定何时需要

【问题讨论】:

  • 你能分享一下错误吗?
  • 这也是一种混淆,因为您给出的标题在类型中看起来像是 -> 的关联,而您的示例是表达式(例如 5 + 3)。

标签: function haskell syntax definition function-declaration


【解决方案1】:

(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

这是因为->是右结合的,所以a -> a -> b实际上是指a -> (a -> b)(取一个a并返回一个函数),这与(a -> a) -> b不同(取一个函数并返回一个@ 987654330@)。

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

【讨论】:

    【解决方案2】:

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

    应用程序关联到左侧

    所以你可以省略函数参数的括号。

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

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

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

    最后:

    给定一个未加括号的表达式 x op y op z,必须在 x op yy op z 周围添加括号,除非有关优先级的某些条件成立

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

    【讨论】:

      【解决方案3】:

      考虑表达式10 / 2 / 5。这和(10 / 2) / 510 / (2 / 5) 一样吗?如果你把/解释为数学除法,那么前者为真,后者为假。所以你看,你的问题的答案是“有区别,但只是有时”。

      类型是相反的。 a -> b -> ca -> (b -> c) 一样,绝对和(a -> b) -> c 不一样。

      你说你不太确定什么时候需要:嗯,就是这样。如果你的函数的参数也是一个函数,那么它是必要的。

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

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

      您可能有兴趣阅读有关柯里化和偏应用的内容。众多资源中的一个好资源:Learn you a Haskell # Curried Functions

      【讨论】:

        【解决方案4】:

        这只有在您创建高阶函数时才会有所不同。例如:

        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
        

        () 的输入规则与普通表达式中的规则几乎相同。就像上一级的表达式。

        【讨论】:

          【解决方案5】:

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

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

          一般来说,当您使用函数作为参数时,您需要在类型中使用括号。例如,map :: (a -> b) -> [a] -> [b]。如果没有括号,则意味着其他内容。

          【讨论】:

            猜你喜欢
            • 2016-02-17
            • 1970-01-01
            • 2021-10-22
            • 1970-01-01
            • 2016-05-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-04-14
            相关资源
            最近更新 更多