Я новичок в Haskell и работаю над упражнением в главе 2 Real World Haskell, где вы пишете функцию, возвращающую предпоследний элемент списка.
Я написал следующую функцию, чтобы попытаться решить эту проблему:
-- file: \Learn Haskell\lastButOne.hs
lastButOne xs = if length xs == 2
then head xs
else lastButOne tail xs
Я не понимаю, что компилятор выдает ошибку:
lastButOne.hs:2:1: error:
• Couldn't match type ‘[a] -> [a]’ with ‘[t]’
Expected type: ([a] -> [a]) -> [t] -> t
Actual type: [t] -> t
• Relevant bindings include
lastButOne :: ([a] -> [a]) -> [t] -> t (bound at lastButOne.hs:2:1)
Насколько я понимаю, ghci считает, что моя функция должна иметь другой тип, чем он есть, но я не понимаю, почему это происходит и как я могу это исправить.
Изменить: Спасибо за ответы! Я обновил свой код:
-- file: \Learn Haskell\lastButOne.hs
lastButOne xs = if length xs == 2
then head xs
else if length xs < 2
then error "This list does not have a second-to-last element."
else lastButOne (tail xs)
Это устраняет ошибку, когда tail xs
интерпретируется как два аргумента, а не как одно выражение. Я также добавил код, который гарантирует, что список не будет слишком коротким. Решение Виллема Ван Онсема лучше, но в качестве упражнения я подумал, что придумал решение, которое использует только концепции, представленные до сих пор в книге.
lastButOne tail xs
равно(lastButOne tail) xs
, а неlastButOne (tail xs)
- person amalloy   schedule 06.07.2017head
,tail
. Они не являются идиоматическим Haskell, поскольку 1) они могут привести к сбою вашей программы, если вы когда-либо будете использовать их в пустом списке, и 2) сопоставление с образцом проще в использовании и к тому же более удобно. - person chi   schedule 06.07.2017