2010-06-07 3 views
10

Я начинаю интересоваться Haskell, и я пытаюсь реализовать план (>> =) самостоятельно, чтобы лучше понять его. В настоящее время у меня естьHaskell FlatMap

flatmap :: (t -> a) -> [t] -> [a] 
flatmap _ [] = [] 
flatmap f (x:xs) = f x : flatmap f xs 

, который реализует «карту», ​​но не «квартиру».
Большинство модификаций я делаю результат в уныние и довольно informationless

Occurs check: cannot construct the infinite type: a = [a] 
    When generalising the type(s) for `flatmap' 

ошибки.

Что мне не хватает?

+3

BTW, есть Википедия, описывающая, что происходит. Проверка: http://en.wikipedia.org/wiki/Occurs_check – jrockway

ответ

19

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

flatmap _ [] = [] 
flatmap f (x:xs) = f x ++ flatmap f xs 

Который, как это происходит, это совершенно правильно. Однако, если вы забыли также изменить подпись типа, произойдет следующее:

Контроллер типа видит, что вы используете ++ по результатам f x и flatmap f xs. Так как ++ работает с двумя списками того же типа, теперь проверяет тип, что оба выражения должны оценивать списки одного и того же типа. Теперь typechecker также знает, что flatmap f xs вернет результат типа [a], поэтому f x также должен иметь тип [a]. Однако в подписи типа указано, что f имеет тип t -> a, поэтому f x должен иметь тип a. Это приводит к проверке типа, чтобы сделать вывод, что [a] = a является противоречием и приводит к появлению сообщения об ошибке.

Если вы измените подпись типа на flatmap :: (t -> [a]) -> [t] -> [a] (или удалите ее), она будет работать.

+0

Спасибо. Это была моя проблема. –

+0

Иногда это также происходит, если вы не укажете подпись типа. – Martijn

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