Я работаю над движком с обратной цепочкой как школьный проект. До сих пор я в основном работал над проектами на C, поэтому решил попробовать Haskell для этого проекта. Я прочитал LYAH, чтобы начать работу, и начал реализовывать представление правил и фактов в моей машине вывода. Пока это то, что у меня есть
module Inference () where
type Op = Bool -> Bool -> Bool
type Label = String
type Fact = (Label, [Rule])
data Rule = Operation Rule Op Rule
| Fact Fact
eval_fact:: [Label] -> Fact -> Bool
eval_fact proved (label,rules) = label `elem` proved || any (eval_rule proved) rules
eval_rule:: [Label] -> Rule -> Bool
eval_rule proved (Fact x) = eval_fact proved x
eval_rule proved (Operation r op r') = eval_rule proved r `op` eval_rule proved r'
Идея состоит в том, чтобы иметь какой-то граф, в котором узлы фактов указывают на узлы правил, если только факт не находится в списке известных фактов.
Однако здесь я сталкиваюсь с проблемой определения моих фактов и правил.
Делать что-то вроде
let fact_e = ("E", [Fact ("C", [(Operation (Fact ("A", [])) (||) (Fact ("B", [])))])])
в ghci для представления правил
C => E
A || B => C
Это работает. Но я действительно не понимаю, в каком направлении двигаться, чтобы программно конструировать эти правила. Более того, я не понимаю, как я могу обрабатывать циклические правила с помощью этой схемы (например, добавляя правило E => A
).
Я видел, что есть способы определить саморегулирующиеся структуры данных в haskell с помощью трюка под названием «Связывание узла» в вики Haskell, но я не понимаю, как (и даже если) мне следует применить это в данном случае.
По сути, мой вопрос заключается в том, иду ли я в правильном направлении, или же я придерживаюсь совершенно противоположного мнения при таком подходе?
PS: Мне также кажется, что мой код не такой лаконичный, как должен быть (прохождение списка [Label], повторение eVal_rule proved
много раз ...), но я действительно не знаю, как это сделать в другом способ.
fact_e
, используя программирование. Для циклических правил вы должны иметь возможность просто поместить их все в одинlet
блок (например,let x1 = val1 <newline> x2 = val2 <newline> x3 = val3 in _
), а лень автоматически отсортирует цикличность. Что касается вашего P.S .: для передачи[Label]
, попробуйте узнать о монадеReader
. Повторениеeval_rule proved
также должно стать немного лучше, если вы используетеReader
. - person bradrn   schedule 21.06.2019let
, вот что я пробовал, спасибо :). - person VannTen   schedule 21.06.2019Fact
вы должны иметь возможность делать это, как и любую другую структуру данных. Например, если у вас естьC => E
, вы можете разделить его на["C", "=>", "E"]
, затем написать функции для преобразования отдельных элементов списка вOperation
и другиеFact
, а затем объединить их вместе с помощью соответствующих конструкторов. Трудно сказать что-то еще, не зная точно, на чем вы застряли; вы боретесь с синтаксическим анализомString
или преобразованием проанализированногоString
вFact
? - person bradrn   schedule 22.06.2019