混淆了haskell中的复合函数

时间:2017-07-25 11:02:36

标签: haskell

let f = show.sum.map read.words
f "1 2"

有效。

show.sum.map read.words "1 2"

我收到错误:

<interactive>:19:19:
    Couldn't match expected type ‘a -> [String]’
                with actual type ‘[String]’
    Relevant bindings include
      it :: a -> String (bound at <interactive>:19:1)
    Possible cause: ‘words’ is applied to too many arguments
    In the second argument of ‘(.)’, namely ‘words "1 2"’
    In the second argument of ‘(.)’, namely ‘map read . words "1 2"’
Prelude> :t show.sum.map
show.sum.map
  :: (Num [b], Show b, Foldable ((->) [a])) => (a -> b) -> String
Prelude> show.sum.map read.words "1 2"

    <interactive>:21:19:
        Couldn't match expected type ‘a -> [String]’
                    with actual type ‘[String]’
        Relevant bindings include
          it :: a -> String (bound at <interactive>:21:1)
        Possible cause: ‘words’ is applied to too many arguments
        In the second argument of ‘(.)’, namely ‘words "1 2"’
        In the second argument of ‘(.)’, namely ‘map read . words "1 2"’
    Prelude> 

我想知道为什么? (show.sum.map read.words)“1 2”也可以工作。

1 个答案:

答案 0 :(得分:8)

问题在于应用程序比应用程序绑定得更紧密,而应用程序实际上具有任何Haskell运算符的最高优先级。这意味着您的代码实际解析

 show.sum.map read.(words "1 2")

不进行类型检查,因为words "1 2"的类型为String,而不是.组成的内容。为了解决这个问题,您可以使用$运算符,该运算符专门用作应用程序,但优先级最低而不是最高优先级。

 show.sum.map read.words $ "1 2"

将按预期工作,因为它具有正确的关联。这通常是为什么你会经常看到foo . bar . baz $ quux的Haskell代码(至少是我的Haskell代码)中的模式。