简体   繁体   English

如何在Haskell中使用两个参数来咖喱函数

[英]How to curry function with two parameters in Haskell

I have a function buckets with type Integral a => [a] -> Int -> Int -> [[a]] and I want use it in foldl in this way: 我有一个类型为Integral a => [a] -> Int -> Int -> [[a]]的函数buckets ,我想以这种方式在foldl中使用它:

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

The function f works, and has a type Integral a => [a] -> Int -> [a] , but if I reduce lst parameter, compilation fails. 函数f起作用,并且具有类型Integral a => [a] -> Int -> [a] ,但是如果我减少lst参数,则编译将失败。

Is it possible to reduce more than one parameter by currying and use f 's body in foldl without declaration of f ? 是否可以通过递归减少多个参数并在不声明f情况下在折叠中使用f的主体? Something like this: 像这样:

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

If you expand the second application of the dot operator: 如果展开点运算符的第二个应用程序:

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

then the eta-reduction becomes obvious: 那么eta减少就变得很明显:

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

But come on, do you really want to do that? 但是,来吧,您真的要这样做吗? Not a very nice present for whoever is going to maintain your code after you're gone. 对于离开后要维护代码的人来说,这不是一个很好的礼物。

First: I recommend not to use flip just to apply a function partially to its second argument; 第一:我建议不要仅使用flip来将函数部分地应用于第二个参数; this can be done better with an infix section. 使用infix部分可以更好地做到这一点。 (Or, perhaps the arguments of bucket should be the other way around in the first place?) (或者,也许bucket的争论首先应该是相反的?)

So, you want to make 所以,你想

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

pointfree. 没有意义。 The problem is that you need to pass two arguments to the rightmost element in the composition chain. 问题是您需要将两个参数传递给组成链中最右边的元素。 One way to do this is to use uncurried form (because then those two arguments come in just a single value): 一种实现方法是使用非咖喱形式(因为这两个参数只是一个值):

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

An alternative is to use specialised combinators. 一种替代方法是使用专用的组合器。 The pointless-fun package has this : pointless-fun包具有以下内容

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

A more standard, though IMO rather ugly alternative is to use the function-functor: you can map over a function, which corresponds to composing after it: 尽管IMO相当丑陋,但更标准的方法是使用function-functor:您可以映射一个函数,这相当于在其后进行编写:

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

The best alternative frankly is to keep that parameter named: 坦率地说,最好的选择是将该参数命名为:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM