├── .github └── workflows │ └── logical_ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── bin ├── dune ├── example.ml ├── friends.ml ├── lovers.ml ├── map_coloring.ml ├── murder_mystery.ml ├── parents.ml └── util.ml ├── docs ├── highlight.pack.js ├── index.html ├── logical │ ├── Logical │ │ ├── .dune-keep │ │ ├── Common_type │ │ │ └── index.html │ │ ├── Goal │ │ │ └── index.html │ │ ├── State │ │ │ └── index.html │ │ ├── Type │ │ │ ├── T │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── Value │ │ │ ├── Type │ │ │ │ └── index.html │ │ │ └── index.html │ │ └── index.html │ ├── Logical__ │ │ ├── .dune-keep │ │ ├── Common_type │ │ │ └── index.html │ │ ├── Goal │ │ │ └── index.html │ │ ├── State │ │ │ └── index.html │ │ ├── Type │ │ │ ├── T │ │ │ │ └── index.html │ │ │ └── index.html │ │ ├── Value │ │ │ ├── Type │ │ │ │ └── index.html │ │ │ └── index.html │ │ └── index.html │ ├── Logical__Common_type │ │ ├── .dune-keep │ │ └── index.html │ ├── Logical__Goal │ │ ├── .dune-keep │ │ └── index.html │ ├── Logical__State │ │ ├── .dune-keep │ │ └── index.html │ ├── Logical__Type │ │ ├── .dune-keep │ │ ├── T │ │ │ └── index.html │ │ └── index.html │ ├── Logical__Value │ │ ├── .dune-keep │ │ ├── Type │ │ │ └── index.html │ │ └── index.html │ └── index.html └── odoc.css ├── dune-project ├── esy.lock ├── .gitattributes ├── .gitignore ├── index.json ├── opam │ ├── alcotest.0.8.5 │ │ └── opam │ ├── astring.0.8.3 │ │ └── opam │ ├── base-bytes.base │ │ └── opam │ ├── base-threads.base │ │ └── opam │ ├── base-unix.base │ │ └── opam │ ├── base.v0.12.2 │ │ └── opam │ ├── biniou.1.2.1 │ │ └── opam │ ├── camomile.1.0.2 │ │ └── opam │ ├── charInfo_width.1.1.0 │ │ └── opam │ ├── cmdliner.1.0.4 │ │ └── opam │ ├── conf-m4.1 │ │ └── opam │ ├── cppo.1.6.6 │ │ └── opam │ ├── dune.1.11.1 │ │ └── opam │ ├── easy-format.1.3.2 │ │ └── opam │ ├── fmt.0.8.8 │ │ └── opam │ ├── fpath.0.7.2 │ │ └── opam │ ├── lambda-term.2.0.2 │ │ └── opam │ ├── lwt.4.2.1 │ │ └── opam │ ├── lwt_log.1.1.1 │ │ └── opam │ ├── lwt_react.1.1.2 │ │ └── opam │ ├── merlin.3.3.2 │ │ └── opam │ ├── mmap.1.1.0 │ │ └── opam │ ├── ocamlbuild.0.14.0 │ │ └── opam │ ├── ocamlfind.1.8.1 │ │ ├── files │ │ │ ├── ocaml-stub │ │ │ └── ocamlfind.install │ │ └── opam │ ├── odoc.1.4.1 │ │ └── opam │ ├── re.1.9.0 │ │ └── opam │ ├── react.1.2.1 │ │ └── opam │ ├── result.1.4 │ │ └── opam │ ├── seq.base │ │ ├── files │ │ │ ├── META.seq │ │ │ └── seq.install │ │ └── opam │ ├── sexplib0.v0.12.0 │ │ └── opam │ ├── stdlib-shims.0.1.0 │ │ └── opam │ ├── topkg.1.0.1 │ │ └── opam │ ├── tyxml.4.3.0 │ │ └── opam │ ├── uchar.0.0.2 │ │ └── opam │ ├── utop.2.4.1 │ │ └── opam │ ├── uuidm.0.9.7 │ │ └── opam │ ├── uutf.1.0.2 │ │ └── opam │ ├── yojson.1.7.0 │ │ └── opam │ └── zed.2.0.3 │ │ └── opam └── overrides │ ├── opam__s__dune_opam__c__1.11.1_opam_override │ └── package.json │ ├── opam__s__ocamlbuild_opam__c__0.14.0_opam_override │ ├── files │ │ └── ocamlbuild-0.14.0.patch │ └── package.json │ └── opam__s__ocamlfind_opam__c__1.8.1_opam_override │ ├── files │ └── findlib-1.8.1.patch │ └── package.json ├── lib ├── dune ├── goal.ml ├── goal.mli ├── logical.ml ├── state.ml ├── state.mli ├── type.ml └── value.ml ├── logical.opam ├── package.json └── test ├── dune ├── goal_test.ml ├── run_tests.ml ├── state_test.ml └── value_test.ml /.github/workflows/logical_ci.yml: -------------------------------------------------------------------------------- 1 | name: Logical CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build-and-test: 7 | runs-on: ${{ matrix.os }} 8 | strategy: 9 | matrix: 10 | os: [ubuntu-latest, macOS-latest] 11 | steps: 12 | - uses: actions/checkout@v1 13 | - uses: actions/setup-node@v1 14 | - name: Install Esy 15 | run: npm install -g esy 16 | - name: Install dependencies 17 | run: esy install 18 | - name: Build the project 19 | run: esy build 20 | - name: Run tests 21 | run: esy test 22 | 23 | build: 24 | runs-on: windows-latest 25 | steps: 26 | - uses: actions/checkout@v1 27 | - uses: actions/setup-node@v1 28 | - name: Install Esy 29 | run: npm install -g esy 30 | - name: Install dependencies 31 | run: esy install 32 | - name: Build the project 33 | run: esy build 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .merlin 2 | node_modules/ 3 | _build 4 | _esy 5 | _release 6 | *.byte 7 | *.native 8 | *.install 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2019 Tóth Róbert 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Logical 2 | 3 | Logical is a minimalistic logic programming inspired by [microKanren](http://minikanren.org/), which is 4 | - Simple implementation with only a few building blocks 5 | - Easy to understand and use 6 | - Supports negation free constraint logic programming 7 | 8 | ## How does it work? 9 | To understand Logical first you need to understands it's basic building blocks which are the following: 10 | - Type 11 | - Value 12 | - State 13 | - Goal 14 | 15 | ### Type 16 | Logical is basically could be seen as a embedded programming language(or DSL), which allows us to use logic programming in Ocaml. It also means that it has it own type system: 17 | ```ocaml 18 | type variable_name = string 19 | 20 | type t = 21 | | Int of int 22 | | Float of float 23 | | Str of string 24 | | Bool of bool 25 | | Var of variable_name 26 | ``` 27 | You can see from the type declaration Logical has all the base types as Ocaml(`Int`, `Float`, `Str`, `Bool`), but also has `Var` for variable declarations. 28 | 29 | ### Value 30 | The value module is responsible for making it easier to create value's based on Logical's type system and has the following constructor functions: 31 | ```ocaml 32 | val int value : int -> int Type.t 33 | 34 | val float value : float -> float Type.t 35 | 36 | val str value = : string -> string Type.t 37 | 38 | val bool value = : bool -> bool Type.t 39 | 40 | val var variable_name : variable_name -> variable_name Type.t 41 | ``` 42 | 43 | ### State 44 | State represents the current state of your program in Logical. State is a map, which stores the value of every currently used variable by using a `variable name -> variable value` association. 45 | It's kind of the same as stack frames in other languages. 46 | 47 | State's signature: 48 | ```ocaml 49 | type state = (variable_name, value) Base.Map.t 50 | ``` 51 | You can clearly see this in state's type declaration, where `variable_name` is the key of the Map and the `value` is the associated value. You can think of state as a list of variable assignments. 52 | 53 | State module's most relevant function are the following: 54 | ```ocaml 55 | (* represents an empty state *) 56 | val empty : state 57 | 58 | (* creates a new state based on the input association list, which gives back None for duplicated variable names *) 59 | val create : (variable_name * t) list -> state option 60 | 61 | (* creates a new state based on the input association list, which gives back an exception for duplicated variable names *) 62 | val create_exn : (variable_name * t) list -> state 63 | 64 | (* gives back the requested logical value based on the provided state *) 65 | val value_of : state -> t -> t 66 | ``` 67 | 68 | ### Goal 69 | Goal is a function, which takes in a state and generates a stream of new states based on that state. The only twist is that sometimes we end up with invalid state(or deadend state), which is why sometimes we can't produce new state based on the input state. 70 | 71 | You can see this in Goal's signature: 72 | ```ocaml 73 | type goal = state -> state option Base.Sequence.t 74 | ``` 75 | 76 | Logical supports the following goals: 77 | ```ocaml 78 | val equal : value -> value -> goal (* A = B *) 79 | 80 | val either : goal -> goal -> goal (* A or B*) 81 | 82 | val either_multi : goal list -> goal (* or [A,B,C,..,Y]*) 83 | 84 | val both : goal -> goal -> goal (* A and B *) 85 | 86 | val both_multi : goal list -> goal (* and [A,B,C,..,Y]*) 87 | 88 | val in_set : value -> value -> goal (* A in (A,B,C,...,Y) *) 89 | ``` 90 | You can see from the type declarations that there are two kinds of goals: 91 | - Basic building block, which expects 2 `value` and generates a `goal`. You can think of them as constructors for goals. 92 | - Goal combinators, which expects 2 `goals` and generates new goals based on that. 93 | 94 | ## How to use it? 95 | General rules for using Logical: 96 | - Goal constructors are the most basic building block of every goal 97 | - Goals can be made bigger and more complex by combining them with goal combinators 98 | - Goals can be grouped by creating custom goals 99 | - Goals are inactive until you give them an initial state 100 | 101 | ### equal 102 | ```ocaml 103 | let equal_goal = Goal.equal (Value.var "a") (Value.int 42) 104 | let state_list = equal_goal State.empty |> Base.Sequence.to_list 105 | (* state_list is [ Some[("a",Value.Int 42)] ]*) 106 | ``` 107 | In this case `state_list` only has one state were `a` is equal with `42`. 108 | 109 | ### either and either_multi 110 | ```ocaml 111 | let a_goal = Goal.equal (Value.var "a") (Value.int 42) 112 | let b_goal = Goal.equal (Value.var "b") (Value.int 21) 113 | let either_goal = Goal.either a_goal b_goal 114 | let state_list = either_goal State.empty |> Base.Sequence.to_list 115 | (* state_list is [ Some[("a",Value.Int 42)]; Some[("b",Value.Int 21)] ]*) 116 | ``` 117 | In this case `state_list` has two states where: 118 | - `a` is equal with `42` 119 | - `b` is equal with `21` 120 | 121 | `either_multi` is the same as `either` only more general, because it expects a list of goals. 122 | ```ocaml 123 | let a_goal = Goal.equal (Value.var "a") (Value.int 42) 124 | let b_goal = Goal.equal (Value.var "b") (Value.int 21) 125 | let goal_list = [a_goal; b_goal] 126 | let either_multi_goal = Goal.either_multi goal_list 127 | let state_list = either_multi_goal State.empty |> Base.Sequence.to_list 128 | (* state_list is [ Some[("a",Value.Int 42)]; Some[("b",Value.Int 21)] ]*) 129 | ``` 130 | 131 | ### both and both_multi 132 | ```ocaml 133 | let a_goal = Goal.equal (Value.var "a") (Value.int 42) 134 | let b_goal = Goal.equal (Value.var "b") (Value.int 21) 135 | let both_goal = Goal.both a_goal b_goal 136 | let state_list = both_goal State.empty |> Base.Sequence.to_list 137 | (* state_list is [ Some[("b",Value.Int 21); ("a",Value.Int 42)] ]*) 138 | ``` 139 | In this case `state_list` has a state with two assignments where: 140 | - `a` is equal with `42` 141 | - `b` is equal with `21` 142 | 143 | `both_multi` is the same as `both` only more general, because it expects a list of goals. 144 | ```ocaml 145 | let a_goal = Goal.equal (Value.var "a") (Value.int 42) 146 | let b_goal = Goal.equal (Value.var "b") (Value.int 21) 147 | let goal_list = [a_goal; b_goal] 148 | let both_multi_goal = Goal.both_multi goal_list 149 | let state_list = both_multi_goal State.empty |> Base.Sequence.to_list 150 | (* state_list is [ Some[("b",Value.Int 21); ("a",Value.Int 42)] ]*) 151 | ``` 152 | 153 | ### in_set 154 | in_set goal is basically a syntactic sugar for an `either_multi` where every goal has the same variable. 155 | ```ocaml 156 | let my_set = Base.Set.of_list (module Type) [Value.int 42; Value.int 21] 157 | let in_set_goal = Goal.in_set (Value.var "a") my_set 158 | let state_list = in_set_goal State.empty |> Base.Sequence.to_list 159 | (* state_list is [ Some[("a",Value.Int 42)]; Some[("a",Value.Int 21)] ]*) 160 | ``` 161 | In this case `state_list` has two states with the same variable(`a`) with two different values: `42` and `21` 162 | 163 | `in_set` goal is useful, when you want negation like `x != 6`, which is basically the same as `x in (-infinity,..,5,7,...,infinity)`. From this example you can also see that in_set is only really useful on small finite domains, where the universal set is small and well defined. 164 | 165 | ### Custom goals 166 | Goal is basically just a function, which accepts a state and based on that generate a sequence of states, so in order to create custom goals you only have to follow the type definition of the goal function, which is: 167 | ```ocaml 168 | type goal = state -> state option Base.Sequence.t 169 | ``` 170 | For example: 171 | ```ocaml 172 | let my_simple_goal state = 173 | (*my_simple_goal's implementation*) 174 | let my_complex_goal custom_input state = 175 | (*my_complex_goal's implementation based on custom_input*) 176 | 177 | let my_big_goal state = 178 | Goal.both_multi [ 179 | my_simple_goal; 180 | my_complex_goal custom_input; 181 | (fun state -> my_simple_goal state) (*Lambda goal*) 182 | (fun state -> my_simple_goal State.empty) (*Independent lambda goal*) 183 | ] state 184 | ``` 185 | 186 | Custom goals are excellent tools for breaking up bigger complex goals into smaller ones and they are also really great fit for generating or creating goals based on some custom extra input parameters. One thing you should be aware is that you are in control of what state you run your custom goals, which gives you a great deal of flexibility. 187 | 188 | **Warning**: using `State.value_of` inside of a custom goal could make it dependent on the order of your other goals. 189 | 190 | ### Note 191 | If you like reading code more than guides than you can find the examples in the `bin` folder in this repository. 192 | 193 | ## How to run the examples? 194 | Prerequisite: Install [Esy](https://esy.sh/) 195 | 196 | Run it: `esy x ` 197 | 198 | For instance: `esy x example` 199 | 200 | ## How to for contributors 201 | Prerequisite: Install [Esy](https://esy.sh/) 202 | 203 | Build it: `esy` 204 | 205 | Test it: `esy test` 206 | 207 | Run repl: `esy utop` 208 | 209 | Generate Doc: `esy doc` 210 | 211 | Update docs folder: `esy update-doc` 212 | 213 | ## Notable resources 214 | - [Hello, declarative world](https://codon.com/hello-declarative-world) 215 | - [miniKanren](http://minikanren.org/) 216 | - [Solving murder with Prolog](https://xmonader.github.io/prolog/2018/12/21/solving-murder-prolog.html) -------------------------------------------------------------------------------- /bin/dune: -------------------------------------------------------------------------------- 1 | (executables 2 | (names example friends parents lovers map_coloring murder_mystery) 3 | (public_names example friends parents lovers map_coloring murder_mystery) 4 | (libraries logical base)) 5 | -------------------------------------------------------------------------------- /bin/example.ml: -------------------------------------------------------------------------------- 1 | open Logical 2 | 3 | let equal_result = Goal.equal (Value.var "a") (Value.int 1) State.empty 4 | let () = Util.print_state_stream "equal_result" equal_result 5 | 6 | let either_result = Goal.either 7 | (Goal.equal (Value.var "a") (Value.int 1)) 8 | (Goal.equal (Value.var "b") (Value.int 2)) 9 | State.empty 10 | let () = Util.print_state_stream "either_result" either_result 11 | 12 | let either_result_multi = Goal.either_multi [ 13 | Goal.equal (Value.var "a") (Value.int 1); 14 | Goal.equal (Value.var "b") (Value.int 2); 15 | Goal.equal (Value.var "b") (Value.int 3); 16 | ] State.empty 17 | let () = Util.print_state_stream "either_result_multi" either_result_multi 18 | 19 | let both_result = Goal.both 20 | (Goal.equal (Value.var "a") (Value.int 1)) 21 | (Goal.equal (Value.var "b") (Value.int 2)) 22 | State.empty 23 | let () = Util.print_state_stream "both_result" both_result 24 | 25 | let both_result_multi = Goal.both_multi [ 26 | Goal.equal (Value.var "a") (Value.int 1); 27 | Goal.equal (Value.var "b") (Value.int 2); 28 | Goal.equal (Value.var "c") (Value.int 3) 29 | ] State.empty 30 | let () = Util.print_state_stream "both_result_multi" both_result_multi 31 | 32 | let my_set = Base.Set.of_list (module Type) [Value.int 1; Value.int 2; Value.int 3] 33 | let in_set_result = Goal.in_set (Value.var "a") my_set State.empty 34 | let () = Util.print_state_stream "in_set_result" in_set_result -------------------------------------------------------------------------------- /bin/friends.ml: -------------------------------------------------------------------------------- 1 | open Logical 2 | 3 | let first_friend_var = "first_friend_var" 4 | let second_friend_var = "second_friend_var" 5 | 6 | let friend first_friend second_friend = 7 | Goal.both 8 | (Goal.equal (Value.var first_friend_var) (Value.str first_friend)) 9 | (Goal.equal (Value.var second_friend_var) (Value.str second_friend)) 10 | 11 | let friend_refl first_friend second_friend = 12 | Goal.either 13 | (friend first_friend second_friend) 14 | (friend second_friend first_friend) 15 | 16 | let friend_db = 17 | Goal.either_multi [ 18 | friend "john" "julia"; 19 | friend "john" "jack"; 20 | friend "julia" "sam"; 21 | friend "julia" "molly"; 22 | ] 23 | 24 | let friend_refl_db = 25 | Goal.either_multi [ 26 | friend_refl "john" "julia"; 27 | friend_refl "john" "jack"; 28 | friend_refl "julia" "sam"; 29 | friend_refl "julia" "molly"; 30 | ] 31 | 32 | let friend_refl_querying first_friend second_friend = 33 | Goal.either 34 | (fun state -> friend_db (State.create_exn [first_friend_var,first_friend; second_friend_var,second_friend])) 35 | (fun state -> friend_db (State.create_exn [first_friend_var,second_friend; second_friend_var,first_friend])) 36 | State.empty 37 | 38 | let friend_querying first_friend second_friend = 39 | friend_refl_db (State.create_exn [first_friend_var, first_friend; second_friend_var, second_friend]) 40 | 41 | let friend_normal_query_state_stream = friend_querying (Value.str "julia") (Value.str "john") 42 | let _ = Util.print_state_stream "Friends: using normal query on refl DB" friend_normal_query_state_stream 43 | 44 | 45 | let friend_refl_query_state_stream = friend_refl_querying (Value.str "julia") (Value.str "john") 46 | let _ = Util.print_state_stream "Friends: using refl query on simple DB" friend_refl_query_state_stream -------------------------------------------------------------------------------- /bin/lovers.ml: -------------------------------------------------------------------------------- 1 | open Logical 2 | 3 | let first_lover_var = "first_lover_var" 4 | let second_lover_var = "second_lover_var" 5 | 6 | let loves first_lover second_lover = 7 | Goal.both 8 | (Goal.equal (Value.var first_lover_var) (Value.str first_lover)) 9 | (Goal.equal (Value.var second_lover_var) (Value.str second_lover)) 10 | 11 | let loves_db = 12 | Goal.either_multi [ 13 | loves "john" "julia"; 14 | loves "julia" "sam"; 15 | loves "sam" "julia"; 16 | ] 17 | 18 | let friendzoned_query lover = 19 | Goal.both_multi [ 20 | (fun state -> loves_db state); 21 | (fun state -> 22 | let other_lover = State.value_of state (Value.var second_lover_var) in 23 | loves_db (State.create_exn [first_lover_var,other_lover; second_lover_var,lover]) 24 | ) 25 | ] (State.create_exn [first_lover_var,lover]) 26 | 27 | let friendzoned_state_stream = friendzoned_query (Value.str "john") 28 | let _ = Base.Sequence.exists friendzoned_state_stream ~f:Base.Option.is_empty |> Printf.printf "Has been friendzoned: %B \n" 29 | let _ = Util.print_state_stream "Lovers querying" friendzoned_state_stream 30 | -------------------------------------------------------------------------------- /bin/map_coloring.ml: -------------------------------------------------------------------------------- 1 | open Logical 2 | 3 | let domain_a_var = Value.var "domain_a_var" 4 | let domain_b_var = Value.var "domain_b_var" 5 | let domain_c_var = Value.var "domain_c_var" 6 | let domain_d_var = Value.var "domain_d_var" 7 | let domain_e_var = Value.var "domain_e_var" 8 | 9 | let universal_set = Base.Set.of_list (module Type) [Value.str "red"; Value.str "green"; Value.str "blue"] 10 | let domain_state_stream = Goal.both_multi [ 11 | Goal.in_set domain_a_var universal_set; 12 | (fun state -> 13 | let smaller_set = Base.Set.remove universal_set (State.value_of state domain_a_var) in 14 | (Goal.both 15 | (Goal.in_set domain_b_var smaller_set) 16 | (Goal.equal domain_b_var domain_d_var)) state); 17 | (fun state -> 18 | let smaller_set = Base.Set.remove universal_set (State.value_of state domain_a_var) in 19 | let even_smaller_set = Base.Set.remove smaller_set (State.value_of state domain_b_var) in 20 | (Goal.both 21 | (Goal.in_set domain_c_var even_smaller_set) 22 | (Goal.equal domain_c_var domain_e_var)) state) 23 | ] State.empty 24 | 25 | let _ = Util.print_state_stream "Solved map coloring:" domain_state_stream -------------------------------------------------------------------------------- /bin/murder_mystery.ml: -------------------------------------------------------------------------------- 1 | open Logical 2 | 3 | let man_set = Base.Set.of_list (module Type) [Value.str "george"; Value.str "john"; Value.str "robert"] 4 | let woman_set = Base.Set.of_list (module Type) [Value.str "barbara"; Value.str "christine"; Value.str "yolanda"] 5 | let person_set = Base.Set.union man_set woman_set 6 | let location_set = Base.Set.of_list (module Type) [Value.str "bathroom"; Value.str "dining"; Value.str "kitchen"; Value.str "living room"; Value.str "pantry"; Value.str "study"] 7 | let weapon_set = Base.Set.of_list (module Type) [Value.str "bag"; Value.str "firearm"; Value.str "gas"; Value.str "knife"; Value.str "poison"; Value.str "rope"] 8 | 9 | let bathroom_var = Value.var "bathroom" 10 | let dining_var = Value.var "dining" 11 | let kitchen_var = Value.var "kitchen" 12 | let living_room_var = Value.var "living room" 13 | let pantry_var = Value.var "pantry" 14 | let study_var = Value.var "study" 15 | 16 | let bag_var = Value.var "bag" 17 | let firearm_var = Value.var "firearm" 18 | let gas_var = Value.var "gas" 19 | let knife_var = Value.var "knife" 20 | let poison_var = Value.var "poison" 21 | let rope_var = Value.var "rope" 22 | 23 | let unique_people_goal person_vars state = 24 | let first_person_var = Base.List.hd_exn person_vars in 25 | let rest_person_vars = Base.List.tl_exn person_vars in 26 | let first_accum_goal = Goal.in_set first_person_var person_set in 27 | let used_person_vars_set = Base.Set.singleton (module Type) first_person_var in 28 | let (result_goals, _) = Base.List.fold rest_person_vars ~init:([first_accum_goal], used_person_vars_set) ~f:(fun (accum_goal, used_person_vars_set) person_var -> 29 | let next_used_person_vars_set = Base.Set.add used_person_vars_set person_var in 30 | let next_goal = (fun state -> 31 | let used_person_set = Base.Set.map (module Type) used_person_vars_set ~f:(fun used_person_var -> State.value_of state used_person_var) in 32 | let available_person_set = Base.Set.diff person_set used_person_set in 33 | Goal.in_set person_var available_person_set state 34 | ) in 35 | (Base.List.append accum_goal [next_goal], next_used_person_vars_set) 36 | ) in 37 | Goal.both_multi result_goals state 38 | 39 | let list_to_str_set list = 40 | let mapped_list = Base.List.map list ~f:(fun element -> Value.str element) in 41 | (Base.Set.of_list (module Type) mapped_list) 42 | 43 | let list_to_var_set list = 44 | let mapped_list = Base.List.map list ~f:(fun element -> Value.var element) in 45 | (Base.Set.of_list (module Type) mapped_list) 46 | 47 | (* You can make this faster by moving the two unique_people_goal calls to the bottom. *) 48 | let murderer x = 49 | Goal.both_multi [ 50 | (fun state -> unique_people_goal [bathroom_var; dining_var; kitchen_var; living_room_var; pantry_var; study_var] state); 51 | (fun state -> unique_people_goal [bag_var; firearm_var; gas_var; knife_var; poison_var; rope_var] state); 52 | Goal.both_multi [Goal.in_set kitchen_var man_set; Goal.in_set kitchen_var (list_to_var_set ["gas"; "poison"])]; 53 | Goal.both_multi [Goal.in_set study_var (list_to_str_set ["barbara"; "yolanda"]); 54 | (fun state -> 55 | let study_val = State.value_of state study_var in 56 | let set_without_study = Base.Set.remove (list_to_str_set ["barbara"; "yolanda"]) study_val in 57 | Goal.in_set bathroom_var set_without_study state)]; 58 | Goal.both_multi [ 59 | (fun state -> 60 | let person_without_bg_set = Base.Set.diff person_set (list_to_str_set ["barbara"; "george"]) in 61 | Goal.in_set bag_var person_without_bg_set state 62 | ); 63 | (fun state -> 64 | let variable_set = list_to_var_set ["kitchen"; "living room"; "pantry"; "study"] in 65 | Goal.in_set bag_var variable_set state 66 | )]; 67 | Goal.both_multi [Goal.in_set rope_var woman_set; Goal.equal rope_var study_var]; 68 | (fun state -> 69 | let jg_set = list_to_str_set ["john"; "george"] in 70 | Goal.in_set living_room_var jg_set state 71 | ); 72 | (fun state -> 73 | let variable_set = list_to_var_set ["bathroom"; "kitchen"; "living room"; "pantry"; "study"] in 74 | Goal.in_set knife_var variable_set state 75 | ); 76 | (fun state -> 77 | let variable_set = list_to_var_set ["bathroom"; "dining"; "kitchen"; "living room"] in 78 | Goal.in_set (Value.str "yolanda") variable_set state 79 | ); 80 | Goal.equal firearm_var (Value.str "george"); 81 | Goal.both_multi [Goal.equal pantry_var gas_var; Goal.equal pantry_var x] 82 | ] 83 | 84 | let x = Value.var "x" 85 | 86 | let murder_stream = murderer x State.empty 87 | 88 | let _ = Util.print_state_stream "Solved murder mystery:" murder_stream -------------------------------------------------------------------------------- /bin/parents.ml: -------------------------------------------------------------------------------- 1 | open Logical 2 | 3 | let male_var = "male_var" 4 | let female_var = "female_var" 5 | 6 | let male male = 7 | Goal.equal (Value.var male_var) (Value.str male) 8 | 9 | let female female = 10 | Goal.equal (Value.var female_var) (Value.str female) 11 | 12 | let male_db = 13 | Goal.either_multi [ 14 | male "brand"; 15 | male "john"; 16 | male "jim"; 17 | male "alfred"; 18 | ] 19 | 20 | let female_db = 21 | Goal.either_multi [ 22 | female "marry" 23 | ] 24 | 25 | let child_var = "child_var" 26 | let parent_var = "parent_var" 27 | 28 | let child child parent = 29 | Goal.both 30 | (Goal.equal (Value.var child_var) (Value.str child)) 31 | (Goal.equal (Value.var parent_var) (Value.str parent)) 32 | 33 | let child_db = 34 | Goal.either_multi [ 35 | child "brad" "alfred"; 36 | child "john" "jim"; 37 | child "john" "marry"; 38 | ] 39 | 40 | let parent_querying parent child = 41 | child_db (State.create_exn [child_var,child; parent_var,parent]) 42 | 43 | let parent_state_stream = parent_querying (Value.str "jim") (Value.str "john") 44 | let _ = Util.print_state_stream "Parent querying" parent_state_stream 45 | 46 | let father_querying father child = 47 | Goal.both 48 | (Goal.equal (Value.var parent_var) (Value.var male_var)) 49 | (Goal.both child_db male_db) 50 | (State.create_exn [child_var,child; parent_var,father; male_var,father]) 51 | 52 | let father_state_stream = father_querying (Value.str "jim") (Value.str "john") 53 | let _ = Util.print_state_stream "Father querying" father_state_stream 54 | 55 | let mother_querying mother child = 56 | Goal.both 57 | (Goal.equal (Value.var parent_var) (Value.var female_var)) 58 | (Goal.both child_db female_db) 59 | (State.create_exn [child_var,child; parent_var,mother; female_var,mother]) 60 | 61 | let mother_state_stream = mother_querying (Value.str "marry") (Value.str "john") 62 | let _ = Util.print_state_stream "Mother querying" mother_state_stream -------------------------------------------------------------------------------- /bin/util.ml: -------------------------------------------------------------------------------- 1 | open Logical 2 | 3 | let sequence_to_list sequece = 4 | sequece |> Base.Sequence.to_list |> Base.List.filter_opt 5 | 6 | let print_state_stream title state_stream = 7 | print_endline title; 8 | state_stream |> sequence_to_list |> 9 | Base.List.iter ~f:(fun element -> 10 | State.to_string element |> print_endline 11 | ); 12 | print_newline () -------------------------------------------------------------------------------- /docs/highlight.pack.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ 2 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(//g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){s+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"
":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("ocaml",function(e){return{aliases:["ml"],k:{keyword:"and as assert asr begin class constraint do done downto else end exception external for fun function functor if in include inherit! inherit initializer land lazy let lor lsl lsr lxor match method!|10 method mod module mutable new object of open! open or private rec sig struct then to try type val! val virtual when while with parser value",built_in:"array bool bytes char exn|5 float int int32 int64 list lazy_t|5 nativeint|5 string unit in_channel out_channel ref",literal:"true false"},i:/\/\/|>>/,l:"[a-z_]\\w*!?",c:[{cN:"literal",b:"\\[(\\|\\|)?\\]|\\(\\)",r:0},e.C("\\(\\*","\\*\\)",{c:["self"]}),{cN:"symbol",b:"'[A-Za-z_](?!')[\\w']*"},{cN:"type",b:"`[A-Z][\\w']*"},{cN:"type",b:"\\b[A-Z][\\w']*",r:0},{b:"[a-z_]\\w*'[\\w']*",r:0},e.inherit(e.ASM,{cN:"string",r:0}),e.inherit(e.QSM,{i:null}),{cN:"number",b:"\\b(0[xX][a-fA-F0-9_]+[Lln]?|0[oO][0-7_]+[Lln]?|0[bB][01_]+[Lln]?|[0-9][0-9_]*([Lln]|(\\.[0-9_]*)?([eE][-+]?[0-9_]+)?)?)",r:0},{b:/[-=]>/}]}}); -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | index 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |

OCaml package documentation

13 |
    14 |
  1. logical 0.3.0
  2. 15 |
16 |
17 |
18 | 19 | -------------------------------------------------------------------------------- /docs/logical/Logical/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StrykerKKD/Logical/bbe349683c6fc9d73c805287839b75e1761fe44b/docs/logical/Logical/.dune-keep -------------------------------------------------------------------------------- /docs/logical/Logical/Common_type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Common_type (logical.Logical.Common_type)

Module Logical.Common_type

type variable = string
type assignment = variable * Value.Type.t
type state = assignment list
type goal = state -> state Base.Sequence.t
-------------------------------------------------------------------------------- /docs/logical/Logical/Goal/index.html: -------------------------------------------------------------------------------- 1 | 2 | Goal (logical.Logical.Goal)

Module Logical.Goal

val equal : Type.t -> Type.t -> Type.goal
val either : Type.goal -> Type.goal -> Type.goal
val either_multi : Type.goal list -> Type.goal
val both : Type.goal -> Type.goal -> Type.goal
val both_multi : Type.goal list -> Type.goal
val in_set : Type.t -> (Type.tType.comparator_witness) Base.Set.t -> Type.goal
-------------------------------------------------------------------------------- /docs/logical/Logical/State/index.html: -------------------------------------------------------------------------------- 1 | 2 | State (logical.Logical.State)

Module Logical.State

val empty : Type.state
val create : (Type.variable_name * Type.t) list -> Type.state option
val create_exn : (Type.variable_name * Type.t) list -> Type.state
val value_of : Type.state -> Type.t -> Type.t
val unify : Type.state -> Type.t -> Type.t -> Type.state option
val to_string : Type.state -> string
-------------------------------------------------------------------------------- /docs/logical/Logical/Type/T/index.html: -------------------------------------------------------------------------------- 1 | 2 | T (logical.Logical.Type.T)

Module Type.T

type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable_name
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical/Type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Type (logical.Logical.Type)

Module Logical.Type

type variable_name = string
module T : sig ... end
include T
type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable_name
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
include sig ... end
type comparator_witness = Base__Comparator.Make(T).comparator_witness
val comparator : (T.tcomparator_witness) Base__Comparator.comparator
type state = (variable_namet, Base.String.comparator_witness) Base.Map.t
type goal = state -> state option Base.Sequence.t
-------------------------------------------------------------------------------- /docs/logical/Logical/Value/Type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Type (logical.Logical.Value.Type)

Module Value.Type

type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable
| Set of (tComparator.comparator_witness) Base.Set.t
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical/Value/index.html: -------------------------------------------------------------------------------- 1 | 2 | Value (logical.Logical.Value)

Module Logical.Value

val int : int -> Type.t
val float : float -> Type.t
val str : string -> Type.t
val bool : bool -> Type.t
val var : Type.variable_name -> Type.t
val to_string : Type.t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical/index.html: -------------------------------------------------------------------------------- 1 | 2 | Logical (logical.Logical)

Module Logical

module Type : sig ... end
module Value : sig ... end
module State : sig ... end
module Goal : sig ... end
-------------------------------------------------------------------------------- /docs/logical/Logical__/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StrykerKKD/Logical/bbe349683c6fc9d73c805287839b75e1761fe44b/docs/logical/Logical__/.dune-keep -------------------------------------------------------------------------------- /docs/logical/Logical__/Common_type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Common_type (logical.Logical__.Common_type)

Module Logical__.Common_type

type variable = string
type assignment = variable * Logical.Value.Type.t
type state = assignment list
type goal = state -> state Base.Sequence.t
-------------------------------------------------------------------------------- /docs/logical/Logical__/Goal/index.html: -------------------------------------------------------------------------------- 1 | 2 | Goal (logical.Logical__.Goal) -------------------------------------------------------------------------------- /docs/logical/Logical__/State/index.html: -------------------------------------------------------------------------------- 1 | 2 | State (logical.Logical__.State)

Module Logical__.State

val empty : Logical.Type.state
val create : (Logical.Type.variable_name * Logical.Type.t) list -> Logical.Type.state option
val create_exn : (Logical.Type.variable_name * Logical.Type.t) list -> Logical.Type.state
val value_of : Logical.Type.state -> Logical.Type.t -> Logical.Type.t
val unify : Logical.Type.state -> Logical.Type.t -> Logical.Type.t -> Logical.Type.state option
val to_string : Logical.Type.state -> string
-------------------------------------------------------------------------------- /docs/logical/Logical__/Type/T/index.html: -------------------------------------------------------------------------------- 1 | 2 | T (logical.Logical__.Type.T)

Module Type.T

type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable_name
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical__/Type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Type (logical.Logical__.Type)

Module Logical__.Type

type variable_name = string
module T : sig ... end
include T
type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable_name
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
include sig ... end
type comparator_witness = Base__Comparator.Make(T).comparator_witness
val comparator : (T.tcomparator_witness) Base__Comparator.comparator
type state = (variable_namet, Base.String.comparator_witness) Base.Map.t
type goal = state -> state option Base.Sequence.t
-------------------------------------------------------------------------------- /docs/logical/Logical__/Value/Type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Type (logical.Logical__.Value.Type)

Module Value.Type

type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable
| Set of (tComparator.comparator_witness) Base.Set.t
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical__/Value/index.html: -------------------------------------------------------------------------------- 1 | 2 | Value (logical.Logical__.Value)

Module Logical__.Value

val int : int -> Logical.Type.t
val float : float -> Logical.Type.t
val str : string -> Logical.Type.t
val bool : bool -> Logical.Type.t
val var : Logical.Type.variable_name -> Logical.Type.t
val to_string : Logical.Type.t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical__/index.html: -------------------------------------------------------------------------------- 1 | 2 | Logical__ (logical.Logical__)

Module Logical__

module Goal : sig ... end
module State : sig ... end
module Type : sig ... end
module Value : sig ... end
-------------------------------------------------------------------------------- /docs/logical/Logical__Common_type/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StrykerKKD/Logical/bbe349683c6fc9d73c805287839b75e1761fe44b/docs/logical/Logical__Common_type/.dune-keep -------------------------------------------------------------------------------- /docs/logical/Logical__Common_type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Logical__Common_type (logical.Logical__Common_type)

Module Logical__Common_type

type variable = string
type assignment = variable * Logical.Value.Type.t
type state = assignment list
type goal = state -> state Base.Sequence.t
-------------------------------------------------------------------------------- /docs/logical/Logical__Goal/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StrykerKKD/Logical/bbe349683c6fc9d73c805287839b75e1761fe44b/docs/logical/Logical__Goal/.dune-keep -------------------------------------------------------------------------------- /docs/logical/Logical__Goal/index.html: -------------------------------------------------------------------------------- 1 | 2 | Logical__Goal (logical.Logical__Goal) -------------------------------------------------------------------------------- /docs/logical/Logical__State/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StrykerKKD/Logical/bbe349683c6fc9d73c805287839b75e1761fe44b/docs/logical/Logical__State/.dune-keep -------------------------------------------------------------------------------- /docs/logical/Logical__State/index.html: -------------------------------------------------------------------------------- 1 | 2 | Logical__State (logical.Logical__State)

Module Logical__State

val empty : Logical.Type.state
val create : (Logical.Type.variable_name * Logical.Type.t) list -> Logical.Type.state option
val create_exn : (Logical.Type.variable_name * Logical.Type.t) list -> Logical.Type.state
val value_of : Logical.Type.state -> Logical.Type.t -> Logical.Type.t
val unify : Logical.Type.state -> Logical.Type.t -> Logical.Type.t -> Logical.Type.state option
val to_string : Logical.Type.state -> string
-------------------------------------------------------------------------------- /docs/logical/Logical__Type/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StrykerKKD/Logical/bbe349683c6fc9d73c805287839b75e1761fe44b/docs/logical/Logical__Type/.dune-keep -------------------------------------------------------------------------------- /docs/logical/Logical__Type/T/index.html: -------------------------------------------------------------------------------- 1 | 2 | T (logical.Logical__Type.T)

Module Logical__Type.T

type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable_name
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical__Type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Logical__Type (logical.Logical__Type)

Module Logical__Type

type variable_name = string
module T : sig ... end
include T
type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable_name
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
include sig ... end
type comparator_witness = Base__Comparator.Make(T).comparator_witness
val comparator : (T.tcomparator_witness) Base__Comparator.comparator
type state = (variable_namet, Base.String.comparator_witness) Base.Map.t
type goal = state -> state option Base.Sequence.t
-------------------------------------------------------------------------------- /docs/logical/Logical__Value/.dune-keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StrykerKKD/Logical/bbe349683c6fc9d73c805287839b75e1761fe44b/docs/logical/Logical__Value/.dune-keep -------------------------------------------------------------------------------- /docs/logical/Logical__Value/Type/index.html: -------------------------------------------------------------------------------- 1 | 2 | Type (logical.Logical__Value.Type)

Module Logical__Value.Type

type t =
| Int of int
| Float of float
| Str of string
| Bool of bool
| Var of variable
| Set of (tComparator.comparator_witness) Base.Set.t
val compare : t -> t -> int
val sexp_of_t : t -> Base.Sexp.t
val to_string : t -> string
-------------------------------------------------------------------------------- /docs/logical/Logical__Value/index.html: -------------------------------------------------------------------------------- 1 | 2 | Logical__Value (logical.Logical__Value)

Module Logical__Value

val int : int -> Logical.Type.t
val float : float -> Logical.Type.t
val str : string -> Logical.Type.t
val bool : bool -> Logical.Type.t
val var : Logical.Type.variable_name -> Logical.Type.t
val to_string : Logical.Type.t -> string
-------------------------------------------------------------------------------- /docs/logical/index.html: -------------------------------------------------------------------------------- 1 | 2 | index (logical.index)

logical index

Library logical

The entry point of this library is the module: Logical.

-------------------------------------------------------------------------------- /docs/odoc.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | /* Copyright (c) 2016 The odoc contributors. All rights reserved. 3 | Distributed under the ISC license, see terms at the end of the file. 4 | odoc 1.4.1 */ 5 | 6 | /* Fonts */ 7 | @import url('https://fonts.googleapis.com/css?family=Fira+Mono:400,500'); 8 | @import url('https://fonts.googleapis.com/css?family=Noticia+Text:400,400i,700'); 9 | @import url('https://fonts.googleapis.com/css?family=Fira+Sans:400,400i,500,500i,600,600i,700,700i'); 10 | 11 | 12 | /* Reset a few things. */ 13 | 14 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { 15 | margin: 0; 16 | padding: 0; 17 | border: 0; 18 | font-size: inherit; 19 | font: inherit; 20 | line-height: inherit; 21 | vertical-align: baseline; 22 | text-align: inherit; 23 | color: inherit; 24 | background: transparent; 25 | } 26 | 27 | table { 28 | border-collapse: collapse; 29 | border-spacing: 0; 30 | } 31 | 32 | *, *:before, *:after { 33 | box-sizing: border-box; 34 | } 35 | 36 | html { 37 | font-size: 15px; 38 | } 39 | 40 | body { 41 | font-family: "Fira Sans", Helvetica, Arial, sans-serif; 42 | text-align: left; 43 | color: #333; 44 | background: #FFFFFF; 45 | } 46 | 47 | .content { 48 | max-width: 90ex; 49 | margin-left: calc(10vw + 20ex); 50 | margin-right: 4ex; 51 | margin-top: 20px; 52 | margin-bottom: 50px; 53 | font-family: "Noticia Text", Georgia, serif; 54 | line-height: 1.5; 55 | } 56 | 57 | .content>header { 58 | margin-bottom: 30px; 59 | } 60 | 61 | .content>header nav { 62 | font-family: "Fira Sans", Helvetica, Arial, sans-serif; 63 | } 64 | 65 | /* Basic markup elements */ 66 | 67 | b, strong { 68 | font-weight: 500; 69 | } 70 | 71 | i, em { 72 | font-style: italic; 73 | } 74 | 75 | sup { 76 | vertical-align: super; 77 | } 78 | 79 | sub { 80 | vertical-align: sub; 81 | } 82 | 83 | sup, sub { 84 | font-size: 12px; 85 | line-height: 0; 86 | margin-left: 0.2ex; 87 | } 88 | 89 | pre { 90 | margin-top: 0.8em; 91 | margin-bottom: 1.2em; 92 | } 93 | 94 | p, ul, ol { 95 | margin-top: 0.5em; 96 | margin-bottom: 1em; 97 | } 98 | ul, ol { 99 | list-style-position: outside 100 | } 101 | 102 | ul>li { 103 | margin-left: 22px; 104 | } 105 | 106 | ol>li { 107 | margin-left: 27.2px; 108 | } 109 | 110 | li>*:first-child { 111 | margin-top: 0 112 | } 113 | 114 | /* Text alignements, this should be forbidden. */ 115 | 116 | .left { 117 | text-align: left; 118 | } 119 | 120 | .right { 121 | text-align: right; 122 | } 123 | 124 | .center { 125 | text-align: center; 126 | } 127 | 128 | /* Links and anchors */ 129 | 130 | a { 131 | text-decoration: none; 132 | color: #2C5CBD; 133 | } 134 | 135 | a:hover { 136 | box-shadow: 0 1px 0 0 #2C5CBD; 137 | } 138 | 139 | /* Linked highlight */ 140 | *:target { 141 | background-color: rgba(187,239,253,0.3) !important; 142 | box-shadow: 0 0px 0 1px rgba(187,239,253,0.8) !important; 143 | border-radius: 1px; 144 | } 145 | 146 | *:hover>a.anchor { 147 | visibility: visible; 148 | } 149 | 150 | a.anchor:before { 151 | content: "#" 152 | } 153 | 154 | a.anchor:hover { 155 | box-shadow: none; 156 | text-decoration: none; 157 | color: #555; 158 | } 159 | 160 | a.anchor { 161 | visibility: hidden; 162 | position: absolute; 163 | /* top: 0px; */ 164 | /* margin-left: -3ex; */ 165 | margin-left: -1.3em; 166 | font-weight: normal; 167 | font-style: normal; 168 | padding-right: 0.4em; 169 | padding-left: 0.4em; 170 | /* To remain selectable */ 171 | color: #d5d5d5; 172 | } 173 | 174 | .spec > a.anchor { 175 | margin-left: -2.3em; 176 | padding-right: 0.9em; 177 | } 178 | 179 | .xref-unresolved { 180 | color: #2C5CBD; 181 | } 182 | .xref-unresolved:hover { 183 | box-shadow: 0 1px 0 0 #CC6666; 184 | } 185 | 186 | /* Section and document divisions. 187 | Until at least 4.03 many of the modules of the stdlib start at .h7, 188 | we restart the sequence there like h2 */ 189 | 190 | h1, h2, h3, h4, h5, h6, .h7, .h8, .h9, .h10 { 191 | font-family: "Fira Sans", Helvetica, Arial, sans-serif; 192 | font-weight: 400; 193 | margin: 0.5em 0 0.5em 0; 194 | padding-top: 0.1em; 195 | line-height: 1.2; 196 | overflow-wrap: break-word; 197 | } 198 | 199 | h1 { 200 | font-weight: 500; 201 | font-size: 2.441em; 202 | margin-top: 1.214em; 203 | } 204 | 205 | h1 { 206 | font-weight: 500; 207 | font-size: 1.953em; 208 | box-shadow: 0 1px 0 0 #ddd; 209 | } 210 | 211 | h2 { 212 | font-size: 1.563em; 213 | } 214 | 215 | h3 { 216 | font-size: 1.25em; 217 | } 218 | 219 | small, .font_small { 220 | font-size: 0.8em; 221 | } 222 | 223 | h1 code, h1 tt { 224 | font-size: inherit; 225 | font-weight: inherit; 226 | } 227 | 228 | h2 code, h2 tt { 229 | font-size: inherit; 230 | font-weight: inherit; 231 | } 232 | 233 | h3 code, h3 tt { 234 | font-size: inherit; 235 | font-weight: inherit; 236 | } 237 | 238 | h3 code, h3 tt { 239 | font-size: inherit; 240 | font-weight: inherit; 241 | } 242 | 243 | h4 { 244 | font-size: 1.12em; 245 | } 246 | 247 | 248 | /* Preformatted and code */ 249 | 250 | tt, code, pre { 251 | font-family: "Fira Mono", courier; 252 | font-weight: 400; 253 | } 254 | 255 | pre { 256 | padding: 0.1em; 257 | border: 1px solid #eee; 258 | border-radius: 5px; 259 | overflow-x: auto; 260 | } 261 | 262 | p code, li code { 263 | background-color: #f6f8fa; 264 | color: #0d2b3e; 265 | border-radius: 3px; 266 | padding: 0 0.3ex; 267 | } 268 | 269 | p a > code { 270 | color: #2C5CBD; 271 | } 272 | 273 | /* Code blocks (e.g. Examples) */ 274 | 275 | pre code { 276 | font-size: 0.893rem; 277 | } 278 | 279 | /* Code lexemes */ 280 | 281 | .keyword { 282 | font-weight: 500; 283 | } 284 | 285 | /* Module member specification */ 286 | 287 | .spec:not(.include), .spec.include details summary { 288 | background-color: #f6f8fa; 289 | border-radius: 3px; 290 | border-left: 4px solid #5c9cf5; 291 | border-right: 5px solid transparent; 292 | padding: 0.35em 0.5em; 293 | } 294 | 295 | .spec.include details summary:hover { 296 | background-color: #ebeff2; 297 | } 298 | 299 | dl, div.spec, .doc, aside { 300 | margin-bottom: 20px; 301 | } 302 | 303 | dl > dd { 304 | padding: 0.5em; 305 | } 306 | 307 | dd> :first-child { 308 | margin-top: 0; 309 | } 310 | 311 | dl:last-child, dd> :last-child, aside:last-child, article:last-child { 312 | margin-bottom: 0; 313 | } 314 | 315 | dt+dt { 316 | margin-top: 15px; 317 | } 318 | 319 | section+section, section > header + dl { 320 | margin-top: 25px; 321 | } 322 | 323 | .spec.type .variant { 324 | margin-left: 2ch; 325 | } 326 | .spec.type .variant p { 327 | margin: 0; 328 | font-style: italic; 329 | } 330 | .spec.type .record { 331 | margin-left: 2ch; 332 | } 333 | .spec.type .record p { 334 | margin: 0; 335 | font-style: italic; 336 | } 337 | 338 | div.def { 339 | margin-top: 0; 340 | text-indent: -2ex; 341 | padding-left: 2ex; 342 | } 343 | 344 | div.def+div.doc { 345 | margin-left: 1ex; 346 | margin-top: 2.5px 347 | } 348 | 349 | div.doc>*:first-child { 350 | margin-top: 0; 351 | } 352 | 353 | /* The elements other than heading should be wrapped in