2017-02-20 7 views
6

У меня есть небольшая функция Эрланга, которая сравнивает, если два списка равны:сопоставления с образцом в Haskell и Erlang

myEq([], [])   -> true; 
myEq([X|Xs], [X|Ys]) -> myEq(Xs, Ys); 
myEq(_, _)   -> false. 

Сравнение происходит на линии 2, X из [X|Xs] всегда связывается с первым элементом первый список, [X|Ys] соответствует только в том случае, если первые элементы обоих списков равны.

Если я попробую это в Haskell, я получаю сообщение об ошибке: «Конфликтующие определения для x». Возможное решение в Haskell будет:

myEq (x:xs) (y:ys) = if x == y then myEq xs ys else False 

Но я хотел бы знать, если это возможно сделать в Haskell, используя поиск по шаблону?

ответ

10

Нет, в Haskell вы не можете использовать ту же переменную x в начале предложения. Haskell делает не сделать объединительные или проверяет равенство как, например, соответственно Пролог и Erlang делать. Это указывается в отчете о Haskell '98:

Набор образцов, соответствующих каждой игре должен быть линейным --- никакая переменная не допускается более одного раза во всем наборе.

(скопировано, полужирный добавлено)

Единственный способ сделать это с помощью защитного (или любой другой тип проверки в теле, конечно). Однако Вы можете написать это более элегантно, как:

myEq [] [] = True 
myEq (x:xs) (y:ys) | x == y = myEq xs ys 
--     | otherwise = False 
myEq _ _ = False 

otherwise случай может быть опущен, так как Haskell будет Откат на последнем пункте, и, таким образом, вернуть False.

Или, возможно, еще более элегантна:

myEq [] [] = True 
myEq (x:xs) (y:ys) = x == y && myEq xs ys 
myEq _ _ = False 

Лично я считаю, что это лучше, так как здесь вы заявляете явно что x равно y так делает ошибки, как случайно пишу ту же переменную не может произойти. Хотя, конечно, это вопрос вкуса.

+1

Чтобы уточнить: Эрланг тоже не делает унификации. Если переменная встречается несколько раз в шаблоне, компилятор Erlang просто генерирует новые имена для других вхождений и вставляет защитный тест, который требует, чтобы они были равны, точно так же, как вы делали вручную в Haskell. – RichardC

+0

@RichardC: Я переписал ответ на * объединение * и * проверки равенства *. Считаете ли вы, что это лучше справляется с этой проблемой? –

+0

Да, это выглядит лучше. – RichardC

1

№ Любая переменная может быть привязана не более одного раза на стороне соответствия шаблону. Если вы хотите связать переменную дважды, вам придется оценивать ее для унификации.

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