mini_kanren/
lib.rs

1//! Rust implementation of the miniKANREN relational logic language.
2
3#[macro_use]
4mod macros;
5pub mod core;
6pub mod database;
7#[macro_use]
8pub mod goals;
9pub mod prelude;
10pub mod testing;
11
12pub use prelude::*;
13
14#[cfg(test)]
15mod tests {
16    use crate::core::goal::RawGoal;
17    use crate::core::logic_variable::{ReifiedVar, Var};
18    use crate::core::stream::Stream;
19    use crate::core::substitution::Substitution;
20    use crate::core::value::Value;
21    use crate::goals::combinators::{conj2, disj2, ifte};
22    use crate::goals::primitive::{alwayso, eq, fail, succeed};
23    use crate::{defrel, disj, fresh, run, substitution};
24    use std::borrow::Cow;
25    use std::collections::HashMap;
26
27    #[test]
28    fn it_works() {
29        let u = Var::new("u");
30        let v = Var::new("v");
31        let w = Var::new("w");
32        let x = Var::new("x");
33        let y = Var::new("y");
34        let z = Var::new("z");
35
36        assert!(Substitution::empty().occurs(&x, &Value::var(x.clone())));
37        assert!(substitution! {y: x}.occurs(&x, &Value::cons(Value::var(y), ())));
38        assert!(substitution! {y: x}.occurs(&x, &vec![Value::var(y)].into()));
39        assert!(Substitution::empty()
40            .extend(x.clone(), vec![Value::var(x.clone())].into())
41            .is_none());
42        assert!(substitution! {y: x}
43            .extend(x.clone(), vec![Value::var(y.clone())].into())
44            .is_none());
45
46        assert_eq!(
47            Substitution::empty().unify(
48                &Value::new(Some(Value::var(x.clone()))),
49                &Value::new(Some(Value::var(y.clone())))
50            ),
51            Some(substitution!(x: y)),
52        );
53
54        assert_eq!(
55            Substitution::empty()
56                .unify(
57                    &Value::new(Some(Value::var(x.clone()))),
58                    &Value::new(Some(Value::var(y.clone())))
59                )
60                .unwrap()
61                .unify(
62                    &Value::new(Some(Value::var(x.clone()))),
63                    &Value::new(Some(Value::new(42)))
64                ),
65            Some(substitution!(x: y, y: 42)),
66        );
67
68        assert_eq!(
69            eq(x, Value::var(u.clone())).apply(Substitution::empty()),
70            Stream::singleton(substitution!(x: u))
71        );
72        assert_eq!(
73            eq(x, 42).apply(Substitution::empty()),
74            Stream::singleton(substitution!(x: 42))
75        );
76        assert_eq!(
77            eq(42, 42).apply(Substitution::empty()),
78            Stream::singleton(substitution!())
79        );
80        assert_eq!(eq(42, 123).apply(Substitution::empty()), Stream::empty());
81
82        assert_eq!(fail().apply(Substitution::empty()), Stream::Empty);
83        assert_eq!(eq(true, false).apply(Substitution::empty()), Stream::Empty);
84        assert_eq!(
85            eq(x, y).apply(Substitution::empty()),
86            Stream::singleton(substitution! {x: y})
87        );
88
89        assert_eq!(
90            disj2(eq("olive", x), eq("oil", x)).apply(Substitution::empty()),
91            Stream::cons(
92                substitution! {x: "olive"},
93                Stream::cons(substitution! {x: "oil"}, Stream::empty())
94            )
95        );
96
97        // no value - stack overflow
98        //assert_eq!(nevero()(Substitution::empty()).take_inf(1), Stream::Empty);
99
100        assert_eq!(
101            alwayso().apply(Substitution::empty()).take_inf(3),
102            Stream::from_iter(
103                vec![
104                    Substitution::empty(),
105                    Substitution::empty(),
106                    Substitution::empty()
107                ]
108                .into_iter()
109            )
110        );
111
112        assert_eq!(
113            disj2(eq("olive", x), eq("oil", x))
114                .apply(Substitution::empty())
115                .take_inf(5)
116                .len(),
117            Some(2)
118        );
119
120        assert_eq!(
121            conj2(eq("olive", x), eq("oil", x)).apply(Substitution::empty()),
122            Stream::empty()
123        );
124
125        assert_eq!(
126            conj2(eq("olive", x), eq(y.clone(), x.clone())).apply(Substitution::empty()),
127            Stream::singleton(substitution! {y: "olive", x: "olive"})
128        );
129
130        let a1 = Value::from(vec![
131            Value::from(u),
132            Value::from(w),
133            Value::from(y),
134            Value::from(z),
135            Value::from(Some(Value::from(vec![Value::from("ice"), Value::from(z)]))),
136        ]);
137        let a2 = Value::from("corn");
138        let a3 = Value::from(vec![Value::from(v), Value::from(u)]);
139        let s = substitution! {x: a1, y: a2, w: a3};
140        //println!("{:?}", reify((&x).into())(s));
141        assert_eq!(
142            s.reify(&x.into()),
143            Value::from(vec![
144                Value::from(ReifiedVar(0)),
145                Value::from(vec![Value::from(ReifiedVar(1)), Value::from(ReifiedVar(0))]),
146                Value::from("corn"),
147                Value::from(ReifiedVar(2)),
148                Value::from(vec![Value::from("ice"), Value::from(ReifiedVar(2))])
149            ])
150        );
151
152        assert_eq!(
153            disj2(eq("olive", x), eq("oil", x))
154                .run(5)
155                .into_iter()
156                .map(|s| s.reify(&x.into()))
157                .collect::<Vec<_>>(),
158            vec![Value::from("olive"), Value::from("oil")],
159        );
160
161        assert_eq!(
162            ifte(succeed(), eq(false, y.clone()), eq(true, y.clone())).apply(Substitution::empty()),
163            Stream::singleton(substitution!(y: false))
164        );
165
166        assert_eq!(
167            ifte(fail(), eq(false, y.clone()), eq(true, y.clone())).apply(Substitution::empty()),
168            Stream::singleton(substitution!(y: true))
169        );
170
171        assert_eq!(
172            disj!(eq("virgin", x); eq("olive", x); eq("oil", x)).apply(Substitution::empty()),
173            Stream::from_iter(
174                vec![
175                    substitution! {x: "virgin"},
176                    substitution! {x: "olive"},
177                    substitution! {x: "oil"},
178                ]
179                .into_iter()
180            )
181        );
182
183        defrel! {
184            teacup(t) {
185                disj!(eq("tea", t.clone()); eq("cup", t))
186            }
187        }
188
189        assert_eq!(
190            teacup(x.clone())
191                .apply(Substitution::empty())
192                .into_iter()
193                .collect::<Vec<_>>(),
194            vec![substitution!(x: "tea"), substitution!(x: "cup")]
195        );
196
197        assert_eq!(
198            format!(
199                "{:?}",
200                fresh!((x, y), eq(x, y)).apply(Substitution::empty())
201            ),
202            "({x: y})"
203        );
204
205        assert_eq!(run!(1, x,), Stream::singleton(Value::from(ReifiedVar(0))));
206        assert_eq!(run!(1, x, eq(x, 42)), Stream::singleton(Value::new(42)));
207        assert_eq!(
208            run!(1, (x, y),),
209            Stream::singleton(Value::new(vec![
210                Value::from(ReifiedVar(0)),
211                Value::from(ReifiedVar(1))
212            ]))
213        );
214        assert_eq!(
215            run!(1, (x, y), eq(x, 42)),
216            Stream::singleton(Value::new(vec![Value::new(42), Value::from(ReifiedVar(0))]))
217        );
218
219        defrel! {
220            conso(a, d, p) {
221                eq(vec![a, d], p)
222            }
223        }
224
225        assert_eq!(
226            run!(*, x, conso(1, 2, x)),
227            Stream::singleton(Value::new(vec![Value::new(1), Value::new(2)]))
228        );
229        assert_eq!(
230            run!(*, x, conso(1, x, vec![Value::new(1), Value::new(2)])),
231            Stream::singleton(Value::new(2))
232        );
233        assert_eq!(
234            run!(*, x, conso(x, 2, vec![Value::new(1), Value::new(2)])),
235            Stream::singleton(Value::new(1))
236        );
237        assert_eq!(
238            run!(*, x, conso(x.clone(), x, vec![Value::new(1), Value::new(2)])),
239            Stream::empty()
240        );
241        assert_eq!(
242            run!(*, x, conso(x.clone(), x, vec![Value::new(3), Value::new(3)])),
243            Stream::singleton(Value::new(3))
244        );
245
246        assert_eq!(
247            run!(5, q, eq(q, "onion")),
248            Stream::singleton(Value::new("onion"))
249        );
250
251        assert_eq!(
252            run!(5, q, eq(q, "onion"), alwayso(),),
253            Stream::from_iter(std::iter::repeat(Value::new("onion")).take(5))
254        );
255    }
256}