为什么在此表达式中用括号替换美元符号($)会导致错误?

时间:2016-07-15 11:34:29

标签: haskell

我有这两个表达式:

  1. foldr (-) 0 . map (uncurry (*)) $ coords 5 7

  2. foldr (-) 0 . map (uncurry (*)) (coords 5 7)

  3. (1)工程打印出结果,但(2)有错误说:

    <interactive>:50:15:
        Couldn't match expected type ‘a -> t0 c’
                    with actual type ‘[Integer]’
        Relevant bindings include
          it :: a -> c (bound at <interactive>:50:1)
        Possible cause: ‘map’ is applied to too many arguments
        In the second argument of ‘(.)’, namely
          ‘map (uncurry (*)) (coords 5 7)’
        In the expression: foldr (-) 0 . map (uncurry (*)) (coords 5 7)
    

    任何人都可以告诉我这两者之间的区别是什么吗?感谢。

3 个答案:

答案 0 :(得分:3)

foldr (-) 0 . map (uncurry (*)) $ coords 5 7
-- is equivalent to
( foldr (-) 0 . map (uncurry (*)) )  (coords 5 7)
-- and to
foldr (-) 0 ( map (uncurry (*)) (coords 5 7) )


foldr (-) 0 . map (uncurry (*)) (coords 5 7)
-- is equivalent to
foldr (-) 0 . ( map (uncurry (*)) (coords 5 7) )
-- and to
\x -> foldr (-) 0 ( map (uncurry (*)) (coords 5 7) x)

在后者中,map (uncurry (*)) (coords 5 7)的结果作为第二个参数传递给.,但它是一个列表,而不是函数,因此会出现类型错误。

注意也可以:

foldr (-) 0 $ map (uncurry (*)) (coords 5 7)

答案 1 :(得分:3)

这是一个更简单的例子:

Prelude> id . id $ "Example"
"Example"
Prelude> id . id ("Example")
<interactive>:2:10:
    Couldn't match expected type ‘a -> c’ with actual type ‘[Char]’
    Relevant bindings include it :: a -> c (bound at <interactive>:2:1)
    In the first argument of ‘id’, namely ‘("Example")’
    In the second argument of ‘(.)’, namely ‘id ("Example")’
    In the expression: id . id ("Example")

问题是函数应用程序的绑定强于(.)($)的固定级别修复了此问题:

id . id $ "Example" = (id . id) $ "Example"
                    = (id . id) "Example"

但是,对于(...),函数应用程序获胜,最终使用(.)作为第二个参数使用非函数:

id . id ("Example") = id . id "Example"
                    = id . (id "Example") -- apply id
                    = id . ("Example")
                    = type error, since "Example" isn't a function

答案 2 :(得分:2)

$只是一个中缀形式的无操作。因为它是一个固定性较低的中缀运算符:

GHCi> :i $
($) :: (a -> b) -> a -> b   -- Defined in ‘GHC.Base’
infixr 0 $

它出现的任何表达式都被解析,好像它有括号。在您的示例中,

foldr (-) 0 . map (uncurry (*)) $ coords 5 7

被解析为

  (   (foldr (-) 0)
    . (map (uncurry (*))) )
$ (coords 5 7)

因为$的固定度低于.。这与您编写1 + 2 * 3的方式完全相同:这被解析为(1) + (2*3),因为*的固定性高于+

$运算符被评估时,它所做的就是将LHS上的函数应用于RHS表达式{在你的情况下,这是foldr (-) 0 . map (uncurry (*)) { {1}}。将函数应用于其参数当然也正是如果您刚刚编写coords 5 7会发生什么,但是您需要指定正确的函数!要为您编写没有function (argument)的示例,您必须将其分组为

$

而你的尝试的解析方式不同:函数应用程序比任何中缀绑定得更紧,甚至( foldr (-) 0 . map (uncurry (*)) ) (coords 5 7) ,所以你的尝试等同于

.

这没有意义。