-
Notifications
You must be signed in to change notification settings - Fork 2
/
example.hs
99 lines (81 loc) · 2.14 KB
/
example.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import Control.Monad.MiniKanren
import Data.List
import Data.Tuple
-- To play with this file, either install the MiniKanrenT package, and
-- open it with ghci directly or (preferably) run with:
-- ghci -isrc example.hs
-- This prints out 5 possible lists that have the symbol "tofu" as a member
exampleMember :: IO ()
exampleMember = mapM_ print $ run 5 $ do
x <- fresh
membero "tofu" x
return x
membero :: (MonadKanren m, CanBeTerm a) => a -> LVar Term -> m ()
membero x xs = do
h <- fresh
t <- fresh
xs === (Cons h t)
conde [ h === x
, membero x t
]
-- Now for the classic genealogy example:
-- Prints out a list of all pairs of siblings
exampleSiblings :: IO ()
exampleSiblings = mapM_ print $
-- filter out any duplicates
nubBy (\a b -> a == b || swap a == b) $
-- filter out any self-siblings
filter (\a -> swap a /= a) $
runAll $ do
x <- fresh
y <- fresh
sibling x y
return (x, y)
-- Prints out a list of all the mothers
exampleMothers :: IO ()
exampleMothers = mapM_ print $ nub $ runAll $ do
m <- fresh
c <- fresh
mother m c
return m
-- Prints out a list of all the fathers
exampleFathers :: IO ()
exampleFathers = mapM_ print $ nub $ runAll $ do
f <- fresh
c <- fresh
father f c
return f
male :: (MonadKanren m, CanBeTerm a) => a -> m ()
male x = conde
[ "Bob" === x
, "Joe" === x
, "Charlie" === x
]
female :: (MonadKanren m, CanBeTerm a) => a -> m ()
female x = conde
[ "Lisa" === x
, "Jenny" === x
, "Andromeda" === x
]
parent :: (MonadKanren m, CanBeTerm a, CanBeTerm b) => a -> b -> m ()
parent p c = conde
[ "Lisa" === p >> "Bob" === c
, "Lisa" === p >> "Andromeda" === c
, "Joe" === p >> "Bob" === c
, "Joe" === p >> "Andromeda" === c
, "Jenny" === p >> "Lisa" === c
, "Jenny" === p >> "Charlie" === c
]
sibling :: (MonadKanren m, CanBeTerm a, CanBeTerm b) => a -> b -> m ()
sibling x y = do
p <- fresh
parent p x
parent p y
mother :: (MonadKanren m, CanBeTerm a, CanBeTerm b) => a -> b -> m ()
mother m c = do
female m
parent m c
father :: (MonadKanren m, CanBeTerm a, CanBeTerm b) => a -> b -> m ()
father m c = do
male m
parent m c