【问题标题】:Haskell dot operatorHaskell 点运算符
【发布时间】:2011-02-19 13:10:00
【问题描述】:

我尝试在 Haskell 中开发一个简单的平均函数。 这似乎有效:

lst = [1, 3]

x = fromIntegral (sum lst)
y = fromIntegral(length lst)

z = x / y

但是为什么下面的版本不起作用?

lst = [1, 3]

x = fromIntegral.sum lst
y = fromIntegral.length lst

z = x / y

【问题讨论】:

标签: haskell syntax function-composition


【解决方案1】:

.(组合)的优先级低于函数应用,所以

fromIntegral.sum lst

被解释为

fromIntegral . (sum lst)

这是错误的,因为sum lst 不是函数。

【讨论】:

    【解决方案2】:

    你被 haskell 的运算符优先级规则绊倒了,这令人困惑。

    当你写作时

    x = fromIntegral.sum lst
    

    Haskell 认为这与:

    x = fromIntegral.(sum lst)
    

    你的意思是:

    x = (fromIntegral.sum) lst
    

    【讨论】:

    • 确实如此。但我认为编写周围没有空格的运算符有时会导致误解(即,它看起来类似于许多以 OOP 为中心的语言中的成员访问构造)。 (fromIntegral . sum) 可能会引起问题,但不会引起误解。
    • 老实说,这里令人困惑的不是 Haskell 的优先规则本身(这很容易说明),而是令人眼花缭乱的(对于初学者而言)运算符数组,每个运算符都有自己的优先级,定义在前奏曲。
    【解决方案3】:

    我只是想添加“$ 来救援!”:

    x = fromIntegral $ sum lst
    y = fromIntegral $ length lst
    

    它的优先级最低,可以避免过多的括号级别。请注意,与 (.) 不同,它不进行函数组合,它计算右侧的参数并将其传递给左侧的函数。类型说明了一切:

    ($) :: (a -> b) -> a -> b
    (.) :: (b -> c) -> (a -> b) -> a -> c
    

    【讨论】:

    • 你也可以写x = fromIntegral . sum $ lst,这更接近于OP最初尝试的内容。
    • 说它评估右边的论点是不相当准确的。评价还是偷懒。为了评估参数,您需要$!。
    • 虽然这个解决方案有效,但我认为这不是正确的答案。对我来说,OP似乎对运算符优先级感到困惑。那么答案是指出适当的优先级并指出括号在这里有帮助。不再介绍另一个运算符。
    • @Martijn:是的,我同意;这就是为什么我从“我只是想添加”开始回答。上面 KennyTM 和 Daniel 的回答解决了优先级问题,我只是添加了一点额外的信息。我的答案绝对不应该被接受,但是在这里拥有它并没有什么坏处
    猜你喜欢
    • 1970-01-01
    • 2014-09-08
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 2021-10-28
    • 1970-01-01
    • 2011-05-04
    • 2022-07-13
    相关资源
    最近更新 更多