如何在 Haskell 中使用两个参数来柯里化函数

How to curry function with two parameters in Haskell

我有一个函数 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参数,编译失败。

是否可以在不声明 f 的情况下通过柯里化和在 foldl 中使用 f 的主体来减少多个参数?像这样:

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

首先:我建议不要使用 flip 只是将函数部分应用于它的第二个参数;这可以通过中缀部分更好地完成。 (或者,也许 bucket 的参数首先应该是相反的?)

所以,你想

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

无积分。问题是您需要将两个参数传递给组合链中最右边的元素。一种方法是使用 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] 

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

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

然后 eta 减少变得明显:

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

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