如何在Haskell

时间:2017-12-13 15:12:07

标签: haskell currying

我有一个类型为buckets的函数Integral a => [a] -> Int -> Int -> [[a]],我希望以这种方式在foldl中使用它:

basketsort lst = foldl (f) lst [1..3]
f lst = reverse . concat . (flip buckets 9) lst

函数f有效,类型为Integral a => [a] -> Int -> [a],但如果我减少lst参数,则编译失败。

是否可以通过curry来减少多个参数,并在不声明f的情况下在foldl中使用f的正文?像这样:

basketsort lst = foldl (reverse . concat . (flip buckets 9)) lst [1..3] 

2 个答案:

答案 0 :(得分:4)

如果展开点运算符的第二个应用程序:

    f lst = reverse . concat . (flip buckets 9) lst
==> f lst = (.) (reverse . concat) ((flip buckets 9) lst)
然后,η减少变得明显:

    f = (.) (reverse . concat) . (flip buckets 9)

但是来吧,你真的想这样做吗?对于那些在你离开之后维护你的代码的人来说,这不是一个很好的礼物。

答案 1 :(得分:2)

首先:我建议不要仅使用flip将函数部分应用于第二个参数;使用中缀部分可以做得更好。 (或者,也许bucket的论点首先应该反过来?)

所以,你要制作

f lst = reverse . concat . (`buckets`9) lst

pointfree。问题是你需要将两个参数传递给合成链中最右边的元素。一种方法是使用 uncurried 形式(因为那时这两个参数只有一个值):

f = curry $ reverse . concat . uncurry (`buckets`9)

另一种方法是使用专门的组合器。 pointless-fun package has this

f = reverse . concat .: (`buckets`9)

一个更标准的,虽然IMO相当丑陋的替代方案是使用函数 - 仿函数:你可以映射一个函数,它对应于后面的组合:

f = fmap (reverse . concat) . (`buckets`9)

最好的替代方法是保持名为

的参数
basketsort lst = foldl (\l -> reverse . concat . buckets l 9) lst [1..3]