Я пытаюсь понять связь между языком логического программирования (Prolog в моем случае) и системой типа Haskell.
Я знаю, как использовать унификацию и переменные для поиска значений (или типов в системе типа Haskell) в зависимости от отношений. В качестве упражнения, чтобы лучше понять сходство и различия между ними, я попытался переписать некоторые простые прологи-программы на уровне типа Haskell, но у меня проблемы с некоторыми частями.
Сначала я переписал эту простую прологическую программу:
numeral(0).
numeral(succ(X)) :- numeral(X).
add(0,Y,Y).
add(succ(X),Y,succ(Z)) :- add(X,Y,Z).
как:
class Numeral a where
numeral :: a
numeral = u
data Zero
data Succ a
instance Numeral Zero
instance (Numeral a) => Numeral (Succ a)
class (Numeral a, Numeral b, Numeral c) => Add a b c | b c -> a where
add :: b -> c -> a
add = u
instance (Numeral a) => Add a Zero a
instance (Add x y z) => Add (Succ x) (Succ y) z
он отлично работает, но я не мог продлить его с помощью этого Пролога:
greater_than(succ(_),0).
greater_than(succ(X),succ(Y)) :- greater_than(X,Y).
Я пробовал это:
class Boolean a
data BTrue
data BFalse
instance Boolean BTrue
instance Boolean BFalse
class (Numeral a, Numeral b, Boolean r) => Greaterthan a b r | a b -> r where
greaterthan :: a -> b -> r
greaterthan = u
instance Greaterthan Zero Zero BFalse
instance (Numeral a) => Greaterthan (Succ a) Zero BTrue
instance (Numeral a) => Greaterthan Zero (Succ a) BFalse
instance (Greaterthan a b BTrue) => Greaterthan (Succ a) (Succ b) BTrue
instance (Greaterthan a b BFalse) => Greaterthan (Succ a) (Succ b) BFalse
Проблема с этим кодом заключается в том, что последние два экземпляра вызывают конфликты с фондом. Я могу понять, почему, но мне кажется, что это не должно быть проблемой, так как их защитные части (или что бы это там называлось, я имею в виду часть (Greaterthan a b c) =>
) различны, так что a
и b
в последние два объявления insance - фактически разные значения, и конфликтов нет.
Другая программа, которую я попыталась переписать, была следующей:
child(anne,bridget).
child(bridget,caroline).
child(caroline,donna).
child(donna,emily).
descend(X,Y) :- child(X,Y).
descend(X,Y) :- child(X,Z),
descend(Z,Y).
(btw, примеры из Learn Prolog Now book)
data Anne
data Bridget
data Caroline
data Donna
data Emily
class Child a b | a -> b where
child :: a -> b
child = u
instance Child Anne Bridget
instance Child Bridget Caroline
instance Child Caroline Donna
instance Child Donna Emily
class Descend a b | b -> a where
descend :: b -> a
descend = u
instance (Child a b) => Descend a b
instance (Child a c, Descend c b) => Descend a b
И я получаю ошибку "дубликатов экземпляров" в последней строке. Я думаю, что это аналогичная проблема, даже если у меня есть разные части защиты, я получаю ошибки, потому что части тела (я имею в виду Descend a b
части) одинаковы.
Итак, я ищу способы портировать программы Prolog на уровень типа Haskell, если это возможно. Любая помощь будет оценена.
EDIT:
Решение Ed'ka работает, но совершенно по-другому. Я все еще пытаюсь понять, когда мы можем запустить программу Prolog в системе типов, когда/почему нам нужно написать другой алгоритм, чтобы заставить его работать (например, в решении Ed'ka), и когда/почему нет пути к внедрить программу в систему типов Haskell.
Возможно, я могу найти некоторые указания об этом после прочтения "Fun With Functional Dependencies".