通过ONE Haskell收缩列表的功能

时间:2014-02-01 23:42:48

标签: haskell

尝试返回删除了最后一个元素的列表。为什么我收到此错误?

ERROR file:.\ShrinkByOne.hs:5 - Type error in application
*** Expression     : (lis !! n : result) lis n
*** Term           : (:)
*** Type           : f -> [f] -> [f]
*** Does not match : a -> b -> c -> d -> e

shrinkByOne :: [Int]  -> [Int]  -> Int ->  [Int]
shrinkByOne result lis n
    | n <= ((length lis) - 2) = shrinkByOne ( ((lis !! n):result) lis n+1) -- this condition prevents the last element from being returned
    | otherwise = result

2 个答案:

答案 0 :(得分:8)

为什么会出错?

在您的原始代码中,您有类似的内容:

shrinkByOne (... something ...)

这意味着您只对shrinkByOne应用了一个参数。你需要这个:

shrinkByOne (... something ...) (... something ...) (... something ...)

因此,以这种方式放括号:

shrinkByOne :: [Int]  -> [Int]  -> Int ->  [Int]
shrinkByOne result lis n
    | n <= ((length lis) - 2) = shrinkByOne ((lis !! n):result) lis (n+1) -- this condition prevents the last element from being returned
    | otherwise = result

其他评论

但是,您仍然无法获得所需的结果,因为结果将被反转,!!代价昂贵,并且您的函数将具有Θ(n²)复杂度。

尝试更简单的线性方法:

shrinkByOne' :: [Int] -> [Int]
shrinkByOne' [x] = []
shrinkByOne' (x : xs) = x : shrinkByOne' xs

最后,我明白这是学习Haskell的练习。如果不是,只需使用Prelude中的init函数。

答案 1 :(得分:4)

首先,你想在函数参数周围省略不必要的parens。 f(x)在Haskell中写成f x(一个只是可选的),特别是如果g (x y)你不能写g :: A -> B -> C,它必须是g x y (或者g (x) (y)。但是g (x y)意味着,您将函数x应用于参数y,并将结果用作g的参数。(如果您确实需要,请写下g $ x yg . x $ y。)

这意味着shrinkByOne ((lis !! n):result) lis n+1。但是,哪个会被解析为(shrinkByOne ((lis !! n):result) lis n) + 1:像+这样的中缀运算符总是比函数应用程序具有更低的优先级,所以确实在n+1周围你需要parens。