haskell - $ 和 () 的区别

标签 haskell functional-programming

我开始学习 Haskell,遇到了一个我无法理解的问题。我有一个用于从键值列表列表中查找值的方法(来自 this page ):

let findKey key xs = snd . head . filter (\(k,v) -> key == k) $ xs  

我试着摆弄了一下,并决定以这种方式摆脱 $ 符号:
let findKey key xs = snd . head . filter (\(k,v) -> key == k) ( xs )

但是,它甚至不解析(过滤器应用于太多参数错误)。我读过 $ 符号用于简单地替换括号,我无法弄清楚为什么这种简单的代码更改是不好的。有人可以向我解释吗?

最佳答案

中缀运算符 ($)只是“功能应用”。换句话说

 f   x     -- and
 f $ x

是相同的。由于在 Haskell 括号中仅用于消除优先级歧义(对于元组表示法和 a few other minor places, see comments ),我们还可以用其他几种方式编写上述内容
 f     x
 f  $  x
(f)    x
 f    (x)
(f)   (x)    -- and even
(f) $ (x)

在每种情况下,上述表达式都表示相同的内容:“将函数 f 应用于参数 x”。

那么为什么有所有这些语法呢? ($)有用有两个原因
  • 它的优先级非常低,因此有时它可以代替很多括号
  • 很高兴为函数应用程序的操作有一个明确的名称


  • 在第一种情况下,考虑以下深度右嵌套函数应用程序
    f (g (h (i (j x))))
    

    阅读这篇文章可能有点困难,知道你有正确数量的括号也有点困难。但是,它“只是”一堆应用程序,所以应该使用 ($) 来表示这个短语。 .确实有
     f $ g $ h $ i $ j $ x
    

    有些人觉得这更容易阅读。更现代的风格还融入了(.)为了强调这个短语的整个左侧只是一个组合的函数管道
     f . g . h . i . j $ x
    

    正如我们在上面看到的,这个短语与
    (f . g . h . i . j)  x
    

    有时更好读。

    有时我们希望能够传递函数应用的想法。例如,如果我们有一个函数列表
    lof :: [Int -> Int]
    lof = [ (+1), (subtract 1), (*2) ]
    

    我们可能想通过一个值来映射应用程序,例如应用数字 4到每个功能
    > map (\fun -> fun 4) lof
    [ 5, 3, 8 ]
    

    但是由于这只是函数应用程序,我们也可以在 ($) 上使用节语法。更明确一点
    > map ($ 4) lof
    [ 5, 3, 8 ]
    

    关于haskell - $ 和 () 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24271129/

    相关文章:

    haskell - 使用 Euterpea/Haskell 演奏随机音符时长

    haskell - 如何定义引用其定义的递归数据类型

    java - 返回 Java 8 流中的第一个匹配项(类似于 _.find)

    java - java 8中两个列表的合并函数

    haskell - 无法将类型 `h' 与 `String' 匹配

    haskell - 在 Haskell 中检测冗余约束?

    regex - 我可以保存正则表达式状态以供下一次输入吗?

    haskell - 'Monad (Writer String)' 的非法实例声明

    haskell - 从 IO 而非计算本身获取值(value)

    graph - OCaml 中以**纯**函数方式实现图的 DFS 和 BFS