-- | /What's in ds-kanren?/ -- -- ['disconj'] -- Try the left and the right and gather solutions that satisfy -- either one. -- ['fresh'] -- Create a fresh logical variable -- ['==='] -- Equate two terms. This will backtrack if we can't unify -- them in this branch. -- ['run'] -- Actually run a logical computation and return results and -- the constraints on them. -- -- In addition to these core combinators, we also export a few -- supplimentary tools. -- -- ['=/='] -- The opposite of '===', ensure that the left and right -- never unify. -- -- /The Classic Example/ -- -- We can define the classic @appendo@ relationship by encoding -- lists in the Lisp "bunch-o-pairs" method. -- -- > appendo :: Term -> Term -> Term -> Predicate -- > appendo l r o = -- > conde [ program [l === "nil", o === r] -- > , manyFresh $ \h t o -> -- > program [ Pair h t === l -- > , appendo t r o -- > , Pair h o === o ]] -- -- Once we have a relationship, we can run it backwards and forwards -- as we can with most logic programs. -- -- >>> let l = list ["foo", "bar"] -- -- >>> map fst . runN 1 $ \t -> appendo t l l -- [nil] -- >>> map fst . runN 1 $ \t -> appendo l t l -- [nil] -- >>> map fst . runN 1 $ \t -> appendo l l t -- [(foo, (bar, (foo, (bar, nil))))] -- -- The toplevel module exports the core language, in -- 'Language.DSKanren.Core' and some simple combinators from -- 'Language.DSKanren.Sugar'. module Language.DSKanren ( module Language.DSKanren.Core , module Language.DSKanren.Sugar ) where import Language.DSKanren.Core import Language.DSKanren.Sugar