[英]perform a function on first elements of list
In an attempt to write the Havel-Hakimi algorithm in Haskell, I wrote following function to subtract 1 from the first n elements of a list. 为了在Haskell中编写Havel-Hakimi算法,我编写了以下函数来从列表的前n个元素中减去1。
decrease_first :: Int -> [Int] -> [Int]
decrease_first 0 l = l
decrease_first n (x:xs) = (x-1):decrease_first (n-1) xs
This code works, but as I am trying to prepare for a Haskell-test and I was convinced this code is rather lame, I wanted to rewrite this function as follows: 这段代码有效,但是当我正在尝试为Haskell测试做准备时,我确信这段代码相当蹩脚,我想重写这个函数如下:
decrease_first :: Int -> [Int] -> [Int]
decrease_first = map (subtract1) . take
I'm aware of the fact this does not do exactly the same, but I was just trying to understand partially applied functions etc. better and wanted to give this function a try. 我知道这不是完全相同的事实,但我只是试图更好地理解部分应用的函数等,并希望尝试这个功能。 This turned out not to be the greatest of ideas, because I didn't get this compiled (type-definitions) and I am left with a massive mind-you-know-what, because next code does work, even though I considered it equivalent: 事实证明这不是最好的想法,因为我没有得到这个编译(类型定义),我留下了一个巨大的思想 - 你知道什么,因为下一个代码确实有效,即使我认为它当量:
decrease_first n = map (subtract1) . take n
and this code fails again: 并且此代码再次失败:
decrease_first n l = map (subtract1) . take n l
Moreover I tried looking for some nice way to apply a function to the first elements of a list, but I couldn't find anything. 此外,我尝试寻找一种很好的方法将函数应用于列表的第一个元素,但我找不到任何东西。 The first way is probably the most efficient way to do it, but I was wondering whether there was some way to apply any function on the first elements of a list. 第一种方式可能是最有效的方法,但我想知道是否有某种方法可以在列表的第一个元素上应用任何函数。 My idea eventually was to do something like: 我的想法最终是做以下事情:
decrease_first n l = map (subtract 1) (take n l) ++ drop n l
It works like this, but it doesn't look as nice as I had it in mind. 它的工作方式与此类似,但它看起来并不像我想象的那么好。 So if anyone could help me resolving my type-issue, I would be very grateful. 所以,如果有人能帮助我解决我的类型问题,我将非常感激。
Thanks in advance 提前致谢
Your first point-free attempts don't work because .
你的第一次无点尝试不起作用,因为.
composes functions with one argument , while take
takes two . 用一个参数组成函数,而take
需要两个 。 What really happens is that code like 真正发生的是代码就像
decrease_first = map (subtract1) . take
is equivalent to 相当于
decrease_first n = map (subtract1) (take n)
but now take n
is not a list, hence a type error arises. 但现在take n
不是列表,因此出现类型错误。
Instead, in 相反,在
decrease_first n l = map (subtract1) . take n l
we have that take nl
is a list, not a function. 我们认为take nl
是一个列表,而不是一个函数。 Here you need application, not function composition eg 在这里你需要应用,而不是功能组合,例如
decrease_first n l = map (subtract1) $ take n l
Your last attempt looks fine to me: 你的最后一次尝试对我来说很好
decrease_first n l = map (subtract 1) (take n l) ++ drop n l
As a variant, you can use splitAt
to get take
& drop
together: 作为一个变体,您可以使用splitAt
得到take
和drop
在一起:
import Data.List
decrease_first n l = map (subtract 1) left ++ right
where (left,right) = splitAt n l
or alternatively: 或者:
decrease_first n l =
(\(left, right) -> map (subtract 1) left ++ right) (splitAt n l)
which is not really better than the above ones. 这并不比上面那些好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.