conda, condi, conde, condu

Я читаю Рассужденный Schemer .

У меня есть интуиция о том, как работает conde .

Однако я не могу найти формального определения того, что делают conde / condu / condu / condu .

Я знаю https://www.cs.indiana.edu/~webyrd/, но, похоже, есть примеры, а не определения.

Существует ли формальное определение conde , condu , condu , condu где-то?

В терминах Prolog condA – это «мягкий разрез» , *-> , а condU«фиксированный выбор» – комбинация once и мягкий разрез, так что (once(A) *-> B ; false) выражает сокращение (A, !, B) :

 A *-> B ; C %% soft cut, condA once(A) *-> B ; C %% committed choice, condU 

В condA , если цель A преуспевает, все решения передаются в первое предложение B и никакие альтернативные предложения C не рассматриваются. once/1 позволяет достичь цели своего аргумента только один раз (сохраняет только одно решение, если оно есть).

condE – простая дизъюнкция, а condI – дизъюнкция, которая чередуется между решениями ее составляющих.


Вот попытка достоверно перевести код книги, логические переменные и унификацию, в 18 строк Haskell (где сопоставление – это приложение с карриной функцией и означает « минусы» ). Смотрите, если это прояснит ситуацию:

  • Последовательная комбинация streamов (« mplus » книги):
  (1) [] ++: ys = ys (2) (x:xs) ++: ys = x:(xs ++: ys) 
  • Комбинация mplusI streamов (« mplusI »):
  (3) [] ++/ ys = ys (4) (x:xs) ++/ ys = x:(ys ++/ xs) 
  • Последовательная подача (” bind “):
  (5) [] >>: g = [] (6) (x:xs) >>: g = gx ++: (xs >>: g) 
  • Альтернативный канал (” bindI “):
  (7) [] >>/ g = [] (8) (x:xs) >>/ g = gx ++/ (xs >>/ g) 
  • « OR » комбинация целейcondE »):
  (9) (f ||: g) x = fx ++: gx 
  • Комбинация цели с чередованием OR (” condI “):
  (10) (f ||/ g) x = fx ++/ gx 
  • « AND » комбинация целей (« all »):
  (11) (f &&: g) x = fx >>: g 
  • «Чередование AND » комбинация целей (« allI » книги):
  (12) (f &&/ g) x = fx >>/ g 
  • Специальные цели
  (13) true x = [x] -- a sigleton list with the same solution repackaged (14) false x = [] -- an empty list, meaning the solution is rejected 

Цели производят streamи (возможно, пустые) (возможно, обновленных) решений, учитывая (возможно, частичное) решение проблемы.

Переписывать правила для all :

 (all) = true (all g1) = g1 (all g1 g2 g3 ...) = (\x -> g1 x >>: (all g2 g3 ...)) === g1 &&: (g2 &&: (g3 &&: ... )) (allI g1 g2 g3 ...) = (\x -> g1 x >>/ (allI g2 g3 ...)) === g1 &&/ (g2 &&/ (g3 &&/ ... )) 

Правила condX для condX :

 (condX) = false (condX (else g1 g2 ...)) = (all g1 g2 ...) === g1 &&: (g2 &&: (...)) (condX (g1 g2 ...)) = (all g1 g2 ...) === g1 &&: (g2 &&: (...)) (condX (g1 g2 ...) (h1 h2 ...) ...) = (ifX g1 (all g2 ...) (ifX h1 (all h2 ...) (...) )) 

Чтобы прийти к окончательному condE и condI , нет необходимости реализовывать ifE и ifI , поскольку они сводятся к простым комбинациям операторов, причем все операторы считаются право-ассоциативными :

 (condE (g1 g2 ...) (h1 h2 ...) ...) = (g1 &&: g2 &&: ... ) ||: (h1 &&: h2 &&: ...) ||: ... (condI (g1 g2 ...) (h1 h2 ...) ...) = (g1 &&: g2 &&: ... ) ||/ (h1 &&: h2 &&: ...) ||/ ... 

Поэтому нет необходимости в каком-либо специальном «синтаксисе» в Haskell, достаточно простых операторов. Любая комбинация может использоваться с &&/ вместо &&: при необходимости. Но OTOH condI также может быть реализовано как функция для принятия коллекции (списка, дерева и т. Д.) condI , которые должны быть выполнены, что будет использовать некоторую разумную страtagsю, чтобы выбрать из них одну наиболее вероятную или наиболее необходимую и т. Д., А не просто простую двоичную чередование, как в ||/ operator (или ifI книги).

Далее, condA книги можно смоделировать двумя новыми операторами ~~> и ||~ , работающими вместе. Мы можем использовать их естественным образом, как, например,

 g1 ~~> g2 &&: ... ||~ h1 ~~> h2 &&: ... ||~ ... ||~ gelse 

который можно интуитивно читать как « IF g1 THEN g2 AND ... OR-ELSE IF h1 THEN ... OR-ELSE gelse ».

  • Комбинация целей « IF-THEN » – это достижение цели «try», которая должна быть вызвана с целью продолжения отказа:
  (15) (g ~~> h) fx = case gx of [] -> fx ; ys -> ys >>: h 
  • OR-ELSE комбинация « OR-ELSE » цели «попробуй» и простая цель просто называет ее «попытку» цели со второй целью бездействия, поэтому это не более чем удобный синтаксис для автоматической группировки операндов:
  (16) (g ||~ f) x = gfx 

Если оператору ||~OR-ELSE ” дана меньшая сила связи, чем оператор ~~>IF-THEN “, и он также является право-ассоциативным, а оператор ~~> имеет еще меньшую силу связи, чем &&: и тому подобное , разумная группировка приведенного выше примера автоматически создается как

 (g1 ~~> (g2 &&: ...)) ||~ ( (h1 ~~> (h2 &&: ...)) ||~ (... ||~ gelse)...) 

Таким образом, последний гол в цепочке ||~ должен быть простой целью. На самом деле это не ограничение, так как последнее предложение condA формы эквивалентно в любом случае простой « AND » -комбинации его целей (или простое false может быть использовано точно также).

Это все. У нас даже может быть больше типов попыток, представленных различными операторами « IF », если мы хотим:

  • используйте переменную подачу в успешной статье (чтобы смоделировать то, что можно было бы назвать condAI , если в книге было одно):
  (17) (g ~~>/ h) fx = case gx of [] -> fx ; ys -> ys >>/ h 
  • используйте успешный stream решения только один раз, чтобы получить эффект разреза , чтобы смоделировать condU :
  (18) (g ~~>! h) fx = case gx of [] -> fx ; (y:_) -> hy 

Итак, наконец, правила condA для condA и condU книги просто:

 (condA (g1 g2 ...) (h1 h2 ...) ...) = g1 ~~> g2 &&: ... ||~ h1 ~~> h2 &&: ... ||~ ... (condU (g1 g2 ...) (h1 h2 ...) ...) = g1 ~~>! g2 &&: ... ||~ h1 ~~>! h2 &&: ... ||~ ... 

Reasoned Schemer охватывает conda (soft cut) и condu (выделенный выбор). Вы также найдете объяснения их поведения в превосходной диссертации Уильяма Берда о мини-Каннрене . Вы отметили это сообщение как о core.logic. Чтобы быть ясным, core.logic основан на более поздней версии miniKanren, чем в представленной в The Reasoned Schemer. miniKanren всегда чередует дизъюнктивные цели – condi и варианты чередования больше не существуют. conde теперь condi .

Например, используя core.logic:

conde будет запускать каждую группу, добиться успеха, если хотя бы одна группа преуспеет, и вернуть все результаты из всех успешных групп.

 user> (run* [wq] (conde [u#] [(or* [(== w 1) (== w 2)]) (== q :first)] [(== q :second)])) ([_0 :second] [1 :first] [2 :first]) 

conda и condu: оба будут останавливаться после первой успешной группы (сверху вниз)

conda возвращает все результаты только из первой успешной группы.

 user> (run* [wq] (conda [u#] [(or* [(== w 1) (== w 2)]) (== q :first)] [(== q :second)])) ([1 :first] [2 :first]) 

condu возвращает только один результат только из первой успешной группы.

 user> (run* [wq] (condu [u#] [(or* [(== w 1) (== w 2)]) (== q :first)] [(== q :second)])) ([1 :first]) 

Не знаю, что такое condi.

  • Как сгенерировать диаграммы UML (особенно диаграммы последовательности) из кода Java?
  • Считать количество элементов в списке на схеме?
  • Какова наилучшая схема базы данных для поддержки значений, которые подходят только для определенных строк?
  • Какой пакет lang подходит для SICP в Dr.Racket?
  • Как хранить массивы в MySQL?
  • В чем разница между eq ?, eqv ?, equal ?, и = в схеме?
  • Сохранение дополнительных данных с заказом в Magento
  • Почему именно это зло?
  • Различия между INDEX, PRIMARY, UNIQUE, FULLTEXT в MySQL?
  • Рекурсивный диапазон в Lisp добавляет период?
  • Разница между схемой / базой данных в MySQL
  • Давайте будем гением компьютера.