代码之家  ›  专栏  ›  技术社区  ›  Kirk Broadhurst

Haskell中的$是什么,以及如何将函数应用于函数[duplicate]

  •  1
  • Kirk Broadhurst  · 技术社区  · 6 年前

    我和Haskell一起做Euler项目,在完成的时候发现了一些要学的东西 the very first problem

    isValid x = (mod x 3 == 0) || (mod x 5 == 0)
    listValid :: Integer -> [Integer]
    listValid n = [x | x <- [1..n-1], isValid x]
    

    函数 listValid n 可以被3或5整除。很简单。

    *Main> listValid 10
    [3,5,6,9]
    

    现在我要把它们加起来。我认为求和函数是正确的方法。我不明白的是为什么前两个版本有效,而第三个版本无效。

    *Main> sum (listValid 10)
    23
    *Main> sum $ listValid 10
    23
    *Main> sum listValid 10
    
    <interactive>:4:5:
        Couldn't match type ‘[Integer]’ with ‘a0 -> t’
        Expected type: Integer -> a0 -> t
          Actual type: Integer -> [Integer]
        Relevant bindings include it :: t (bound at <interactive>:4:1)
        In the first argument of ‘sum’, namely ‘listValid’
        In the expression: sum listValid 10
    

    这是一个操作顺序问题吗?我需要用括号括起来,以断言应该首先应用哪个函数?如果是的话,有什么问题 $

    4 回复  |  直到 6 年前
        1
  •  5
  •   sepp2k    6 年前

    它是关于联想性的。函数应用程序是左关联的,所以 sum listValid 10 相当于 (sum listValid) 10 ,不是 sum (listValid 10) add x y = x+y add 1 2 相当于 add (1 2) .

    所以这里的问题是 总和列表有效10 ,它看不见 listValid 10 sum ; 它看到了 listValid 作为 然后 10 作为 sum listValid .

    $ 解决这个问题是因为它是一个中缀运算符 总和 是它的左操作数 是它的右操作数(请记住,函数应用程序的优先级高于任何中缀运算符,因此不能将其视为 (sum $ listValid) 10 ).

        2
  •  3
  •   chepner    6 年前

    函数应用 f x

    sum listValid 10
    

    相当于 (sum listValid) 10 .

    这个 $

    sum $ listValid 10
    

    sum $ (listValid 10) ,不是 (sum $ listValid) 10

        3
  •  2
  •   willeM_ Van Onsem    6 年前

    当你写作的时候 f $ x ,其实你写的 ($) f x ,与 ($) :: (a -> b) -> a -> b 一个函数。此函数是 defined as

    ($) :: forall r a (b :: TYPE r). (a -> b) -> a -> b
    f $ x = f x
    

    以上这些看起来不太令人印象深刻。如果你这样写 ,相当于 f x ,那么为什么要写一个 $ 不管怎样?因为这个接线员 precedence 0 . 这意味着如果你写:

    f $ x+2
    

    ($) f (x+2)
    

    因此:

    f (x+2)
    

    不需要写括号。

    sum $ listValid 10
    

    ($) (sum) (listValid 10)
    

    sum (listValid 10)
    

    如果你写:

    sum listValid 10
    

    哈斯克尔将此解释为:

    (sum listValid) 10
    

    现在 sum Integer -> [Integer] 没有意义, sum :: Num a => [a] -> a Num 埃里克值,因此错误。

        4
  •  2
  •   Daniel Wagner    6 年前

    函数应用程序是左关联的,所以

    f x y
    

    解析为:

    (f x) y
    

    f x $ g y
    

    解析为:

    (f x) $ (g y)
    

    特别是,您有:

    sum listValid 10 = (sum listValid) 10
    sum $ listValid 10 = sum $ (listValid 10) = sum (listValid 10)