如何在 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)
但是拜托,你真的想那样做吗?对于在您离开后将要维护您的代码的人来说,这不是一个很好的礼物。
我有一个函数 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)
但是拜托,你真的想那样做吗?对于在您离开后将要维护您的代码的人来说,这不是一个很好的礼物。