2013-06-03 4 views
8

я был в состоянии выполнить следующий код безотказноНе удался соответствовать ожидаемому типу `а«с фактическим типом `[а]»

myLast :: [a] -> a 
myLast [] = error "Can't call myLast on an empty list!" 
myLast (x:_) = x 

, но я получаю эту ошибку Couldn't match expected type `a' with actual type `[a]'. `a' is a rigid type variable bound by the type signature for myLast :: [a] -> a для следующего кода:

myLast :: [a] -> a 
myLast [] = error "Can't call myLast on an empty list!" 
myLast (_:x) = x 

Я новичок в Haskell, и сообщение об ошибке слишком греческое и латинское для меня. Из того, что я могу понять, компилятор не может вывести тип во втором случае. Может ли кто-нибудь указать мне на то, что на самом деле происходит здесь?

ответ

13

Вы объявляете ввод как список типов [a], а остальные должны быть типа a.

Список типов a в Haskell состоит из головки типа a и хвоста, списка типов [a]. Конструктор cons : берет голову и хвост в качестве аргументов.

Когда вы деконструируете список как (x:y), x - это голова, а y - это хвост. Таким образом, во втором фрагменте кода вы привязываете хвост списка, который имеет тип списка [a], когда ваша подпись типа требует, чтобы вы возвращали значение типа a (например, голова).

2

(_:x) соответствует _ головой и х с хвостом списка. Тип хвоста списка - [a]. Вы пытаетесь вернуть [a] ', где, поскольку объявление функции указывает тип возвращаемого значения как a.

myLast (_:x) = x 

Если вы хотите, чтобы соответствовать взять последний элемент взглянуть на этот ответ - Can you use pattern matching to bind the last element of a list?

6

Имея понимание того, что : действительно поможет расшифровать сообщение об ошибке. : можно рассматривать как функцию, которая принимает элемент и список, и возвращает список, чей первый элемент является первым аргументом, а остальная часть является второй аргумент, или:

(:) :: a -> [a] -> [a] 

Как добраться до функции, вы написали myLast :: [a] -> a; однако тип myLast (_:x) = x равен myLast :: [a] -> [a], так как второй аргумент : (который вы назвали x) сам по себе является списком.

Кроме того, в общем, если вы не понимаете что-то в Haskell, вы должны сначала взглянуть на его тип, используя :t в GHCI.

Смежные вопросы