2017-02-12 7 views
0

Begginer Haskell Question. На самом деле я нашел очень похож вопрос Haskell error: "non-exhaustive patterns"Еще один «Неисчерпывающие шаблоны в функции»

Интерактивная оболочка:

Prelude> merge [] [] = [] 
Prelude> merge (x:xs) [] = x:xs 
Prelude> merge [] (y:ys) = y:ys 
Prelude> -- merge (x:xs) (y:ys) 

Prelude> merge [][] 
Exception 
Prelude> merge [0][] 
Exception: <interactive>:3:1-22: Non-exhaustive patterns in function merge 

Prelude> merger [][0] 
OK 

В самом деле исключения существуют также в не интерактивном режиме

main = do 
    print (merge [1,2,3] []) 
    print (merge [] [1,2,3]) 
    print (merge [] []) 


merge :: (Ord a) => [a] -> [a] -> [a] 
merge (x:xs) [] = x:xs 
merge [] (y:ys) = y:ys 
merge [][] = [] 

Однако это зависит от порядка particulas частных случаев слияния где появляется ошибка. Я не знаю, почему это происходит. Заранее спасибо.

ответ

6

Здесь есть две отдельные проблемы.

Вы не могли бы определить merge таким образом в GHCi. (Спасибо за исправление, Алик!)

Первый вопрос, который происходит только в интерактивном режиме, в том, что вы определяете три отдельные функции, называемые merge, каждый из которых тени предыдущий. См. here для тех, у кого была очень похожая проблема.

Чтобы ввести единое определение многострочный, вы должны использовать :{ и :}:

Prelude> :{ 
Prelude| merge [] [] = [] 
Prelude| merge (x:xs) [] = x:xs 
Prelude| merge [] (y:ys) = y:ys 
Prelude| -- merge (x:xs) (y:ys) 
Prelude| :} 
Prelude> 

Однако, в целом, вводя многострочные определения в GHCi довольно неприятно, так что вам лучше хранить свои определения в нормальный .hs, а затем загрузить этот файл в GHCi.


Второй вопрос, который происходит как в интерактивном режиме и в не-интерактивной программе, является то, что ваше определение merge не является исчерпывающим: в случае, когда оба аргумента списка непустые не обрабатываются. Обратите внимание, что:

  • Если аргумент списка пуст, merge должен вернуть другой список.
  • Если оба списка непусты, merge должен извлечь наименьший элемент головы (в любом списке), а затем рекурсивно объединить остальные.

Таким образом, правильное определение merge является:

Prelude> :{ 
Prelude| merge xs [] = xs 
Prelude| merge [] ys = ys 
Prelude| merge [email protected](x:xs) [email protected](y:ys) 
Prelude| | x <= y = x : merge xs yys 
Prelude| | otherwise = y : merge xxs ys 
Prelude| :} 
Prelude> merge [1,3..9] [2,4..10] 
[1,2,3,4,5,6,7,8,9,10] 
Prelude> 

Или неинтерактивно:

merge xs [] = xs 
merge [] ys = ys 
merge [email protected](x:xs) [email protected](y:ys) 
    | x <= y = x : merge xs yys 
    | otherwise = y : merge xxs ys 
+0

К сожалению, новая версия GHC действительно позволяет опустить 'let', поэтому каждая строка затмевает предыдущий – Alec

+0

@Alec: TIL. Благодаря! – pyon

+0

Обратите внимание, что вы не только исправили ошибки синтаксиса, но и исправили код. Функция OPs по-прежнему выдает ошибку, если она определена в файле, потому что нет 'merge (x: xs) (y: ys) = ..' case – user2407038