为什么喂养init在Haskell中不起作用?

时间:2015-10-01 18:39:16

标签: list haskell function-composition

所以我写了一行来获取列表的倒数第二个元素。最初我的代码是

mySLast x = last.take ((length x) - 1) x

直到last功能才开始工作。实现我的take业务已经包含在Haskell中init所以我改写为

mySLast = last.init 

这仍然无法奏效。我发现这令人费解,因为init::[a]->[a]last::[a]->a所以它们肯定应该是 Hask 类别中的可组合态射。

我试过问Haskell它认为类型是什么,它说

ghci> :t last.init
last.init :: [c] -> c
ghci> last.init [3,2,4,1]

<interactive>:45:6:
    Couldn't match expected type ‘a -> [c]’
                with actual type ‘[Integer]’
     Relevant bindings include
       it :: a -> c (bound at <interactive>:45:1)
    Possible cause: ‘init’ is applied to too many arguments
     In the second argument of ‘(.)’, namely ‘init [3, 2, 4, 1]’
     In the expression: last . init [3, 2, 4, 1]

即使

ghci> init [3,2,4,1]
[3,2,4]
ghci> last [3,2,4]
4

所以我一定是误解了在Haskell中编写函数的事情。任何见解将不胜感激!

3 个答案:

答案 0 :(得分:10)

函数应用程序的绑定比(.)更紧密,所以

last.init [3,2,4,1]

正在被解析为

last . (init [3,2,4,1])

你可以使用

(last . init) [3,2,4,1]

last . init $ [3,2,4,1]

答案 1 :(得分:1)

您忘记了init和列表之间的$,例如

last . init $ [3,2,4,1]
            ↑ See here 

答案 2 :(得分:1)

这个问题的另一种解决方案,它只评估所需元素的(列表),而不是使用长度(在回到所需元素之前评估整个脊柱):

takeTail n xs = go (drop n xs) xs
  where
    go (_:ys) (_:xs) = go ys xs 
    go []     xs     = xs  -- Stop and return xs when ys runs out

> head . takeTail 2 $ [1,2,3,4]
3