Haskell函数组合方法

时间:2016-09-09 12:01:17

标签: function haskell functional-programming composition

我刚开始在大学学习Haskell,在玩弄它时,我偶然发现了一个我似乎无法掌握的问题。 以下代码为我提供了所需的结果:

import Data.List
list = ["Hello", "world"]

main = print $ intercalate " something " (reverse (map reverse list))

输出:

"dlrow something olleH"

但我想用点而不是括号来编写'main'函数,所以尝试了:

main = print $ intercalate " something " . reverse . map reverse list

然而,这给了我以下错误:

test.hs:5:54: error:
    • Couldn't match expected type ‘a0 -> [[Char]]’
                  with actual type ‘[[Char]]’
    • Possible cause: ‘map’ is applied to too many arguments

我认为这些点与括号完全相同:功能组合。为什么括号有效,而圆点给我一个类型相关的错误?任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:3)

功能组成的等价如下:

main = (print . intercalate " something " . reverse . map reverse) list
main = print . intercalate " something " . reverse . map reverse $ list

或删掉不必要的括号:

map reverse list

在您的尝试中,.是一个单独的表达式,即中缀map reverse运算符的参数,它不起作用 - 您只能编写list函数,并且然后将整个组合函数应用于$userdata = array( 'email' => Input::get('email'), 'password' => Input::get('password') ); if (Auth::attempt($userdata)) { return view('dashboard'); } 参数。

答案 1 :(得分:3)

括号不代表功能构成。它们只是意味着“将这个子表达式组合”。当然,您可以使用来创建一系列函数组合:以下将c定义为函数fg和{{1}的组合}}

h

这也可以写成:

c x = f (g (h x))

因此,你可以

c = f . g . h

但是如果你再次内联main = print $ c list where c = intercalate " something " . reverse . map reverse ,你需要注意不要弄乱解析规则:只是在该组合链的右边写c不会,因为函数应用程序绑定比任何中缀运算符更紧密(包括list,尽管这实际上是最严格的中缀运算符)。即,

.

实际上被解析为

intercalate " something " . reverse . map reverse list

但这不是你想要的。你需要确保(intercalate " something ") . (reverse) . (map reverse list) 实际上是整个组合链的参数,而不仅仅是它的最后一个元素;执行此操作的首选方法是使用list运算符:

$

intercalate " something " . reverse . map reverse $ list 具有最低预设值,因此将其解析为

$

或者,您可以立即将((intercalate " something ") . (reverse) . (map reverse)) (list) 应用于map reverse - 这本身并没有错,只是结果不再是合成链的一部分:

list

答案 2 :(得分:2)

使用.的函数组合意味着该函数将有另一个参数。如果您改为编写以下内容,那就可以了。

main = print $ (intercalate " something " . reverse . map reverse) list

这样,list值是括号内组成的函数的参数。