Подтвердить что ты не робот

Различия между сопоставлением шаблонов и унификацией?

Мне казалось, что я понимаю, как соответствие шаблонов, найденное в Scala, и Haskell отличается от унификации, найденной в Prolog, но мои недопонимания Prolog великолепны. Какие простые проблемы решаются теми, которые не могут быть решены другим? Спасибо вам

4b9b3361

Ответ 1

Простая инструкция: соответствие шаблонов односторонне, унификация является двусторонней. То есть в Prolog правая часть (совпадающая с ней) может включать несвязанные переменные. Например, если у вас есть две несвязанные переменные X и Y, это будет работать нормально:

X = Y,
X = 5,
%% Y = 5 now as well

В Erlang (который использует сопоставление образцов с синтаксисом, близким к Prolog), строка X = Y приведет к ошибке: variable 'Y' is unbound. Обратите внимание, что X является несвязанным в порядке: он должен быть сопоставлен с образцом.

Это может быть полезно, если вы хотите иметь дело с частично определенными значениями. Хорошим примером является список различий.

Это также позволяет использовать предикат Prolog в нескольких режимах. Например. в Scala/Haskell/Erlang, если вы хотите 1) найти A ++ B, 2) решить уравнение A ++ X == B или 3) решить уравнение X ++ A == B для данных списков A и B, вы необходимо написать 3 отдельные функции; в Prolog все эти задания (и многое другое!) выполняются одним предикатом.

Ответ 2

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

  • Термин s соответствует t, если существует подстановка phi такая, что phi (s) = t
  • Член s унифицируется с членом t, если существует такая замена, что phi (s) = phi (t)

Чтобы привести пример, мы проверяем члены s = f (Y, a) и t = f (a, X), где X, Y - переменные, a - постоянная. s не соответствует t, потому что мы не можем универсально количественно определить константу a. Однако существует унификатор для s и t: phi = {X\a, Y\a}

Ответ 3

В Scala не удалось выполнить компиляцию, так как первая ветвь case пытается объявить переменную x дважды.

(1, 1) match{
   case (x, x) => println("equals")
   case _      => println("not equals")
}

Если Scala использовать унификацию вместо соответствия шаблону, это будет успешным и напечатать "равно", а

(1, 2) match{
   case (x, x) => println("equals")
   case _      => println("not equals")
}

будет печатать "не равно". Это происходит из-за сбоя объединения при попытке привязать переменную x к 1 и 2.

Ответ 4

В Prolog вы можете добавить [3] к [1,2] следующим образом:

?- append([1,2], [3], Z).
Z = [1, 2, 3].

Оптимальная вещь об объединении состоит в том, что вы можете использовать один и тот же код (внутреннее определение "append" ), но вместо этого найдите второй аргумент, необходимый для получения результата из первого аргумента:

?- append([1,2], Y, [1,2,3]).
Y = [3].

Вместо того, чтобы кодировать, написав "сделайте это, тогда сделайте это", вы закодируете в Prolog, указав то, что знаете. Пролог рассматривает факты, которые вы даете им как уравнения. Унификация позволяет использовать эти уравнения и решать любые переменные, которые вы еще не знаете значения, независимо от того, находятся они справа или слева.

Итак, например, вы можете написать планировщик в Prolog, и вы можете запустить его "вперед", предоставив ему план и предсказать его результаты; или вы можете запустить его "назад", предоставив ему набор результатов и построив план. Вы можете даже запустить его в обоих направлениях сразу (если вы были осторожны в своем кодировании), указав набор целей и набор ограничений для плана, чтобы вы могли сказать "Найдите план для работы, который не включает взяв метро."