mirror of
https://github.com/Smaug123/FicroKanSharp
synced 2025-10-08 13:08:40 +00:00
Test it
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ obj/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
.idea/
|
||||
*.user
|
||||
|
@@ -5,12 +5,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="UnitTest1.fs" />
|
||||
<Compile Include="TestExamples.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="FsUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
133
FicroKanSharp.Test/TestExamples.fs
Normal file
133
FicroKanSharp.Test/TestExamples.fs
Normal file
@@ -0,0 +1,133 @@
|
||||
namespace FicroKanSharp.Test
|
||||
|
||||
open FicroKanSharp
|
||||
open Xunit
|
||||
open FsUnitTyped
|
||||
|
||||
module TestThing =
|
||||
|
||||
[<Fact>]
|
||||
let ``Example from the docs`` () : unit =
|
||||
let aAndB =
|
||||
Goal.conj
|
||||
(Goal.callFresh (fun x -> Goal.equiv (Term.Variable x) (Term.Literal 7)))
|
||||
(Goal.callFresh (fun x -> Goal.disj (Goal.equiv (Term.Variable x) (Term.Literal 5)) (Goal.equiv (Term.Variable x) (Term.Literal 6))))
|
||||
|
||||
let u = Goal.evaluate aAndB State.empty
|
||||
match u |> Stream.peel with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual
|
||||
[
|
||||
Variable.VariableCount 0, Term.Literal 7
|
||||
Variable.VariableCount 1, Term.Literal 5
|
||||
]
|
||||
|
||||
match rest |> Stream.peel with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual
|
||||
[
|
||||
Variable.VariableCount 0, Term.Literal 7
|
||||
Variable.VariableCount 1, Term.Literal 6
|
||||
]
|
||||
|
||||
match rest |> Stream.peel with
|
||||
| None -> ()
|
||||
| Some s -> failwith $"{s}"
|
||||
|
||||
[<Fact>]
|
||||
let ``Another example`` () =
|
||||
let aAndB =
|
||||
(Goal.callFresh (fun x -> Goal.equiv (Term.Variable x) (Term.Literal 5)))
|
||||
|
||||
let u = Goal.evaluate aAndB State.empty
|
||||
match u |> Stream.peel with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 5]
|
||||
|
||||
match Stream.peel rest with
|
||||
| None -> ()
|
||||
| Some s -> failwithf $"{s}"
|
||||
|
||||
[<Fact>]
|
||||
let ``Recursive example`` () =
|
||||
let rec fives (x : Variable) =
|
||||
(Goal.disj (Goal.equiv (Term.Variable x) (Term.Literal 5)) (Goal.delay (fun () -> fives x)))
|
||||
|
||||
let u = Goal.evaluate (Goal.callFresh fives) State.empty
|
||||
match u |> Stream.peel with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 5]
|
||||
|
||||
match Stream.peel rest with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 5]
|
||||
|
||||
match Stream.peel rest with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, _rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 5]
|
||||
|
||||
[<Fact>]
|
||||
let ``Another recursive example`` () =
|
||||
let rec fives (x : Variable) =
|
||||
(Goal.disj (Goal.equiv (Term.Variable x) (Term.Literal 5)) (Goal.delay (fun () -> fives x)))
|
||||
let rec sixes (x : Variable) =
|
||||
(Goal.disj (Goal.equiv (Term.Variable x) (Term.Literal 6)) (Goal.delay (fun () -> sixes x)))
|
||||
let fivesAndSixes =
|
||||
Goal.callFresh (fun x -> Goal.disj (fives x) (sixes x))
|
||||
|
||||
let u = Goal.evaluate fivesAndSixes State.empty
|
||||
match u |> Stream.peel with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 5]
|
||||
|
||||
match Stream.peel rest with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 6]
|
||||
|
||||
match Stream.peel rest with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 5]
|
||||
|
||||
match Stream.peel rest with
|
||||
| None -> failwith "oh no"
|
||||
| Some (s, _rest) ->
|
||||
|
||||
s
|
||||
|> Map.toList
|
||||
|> shouldEqual [Variable.VariableCount 0, Term.Literal 6]
|
@@ -1,10 +0,0 @@
|
||||
namespace FicroKanSharp.Test
|
||||
|
||||
open FicroKanSharp
|
||||
open Xunit
|
||||
|
||||
module TestThing =
|
||||
|
||||
[<Fact>]
|
||||
let ``Foo`` () : unit =
|
||||
failwith "TODO!"
|
6
FicroKanSharp/AssemblyInfo.fs
Normal file
6
FicroKanSharp/AssemblyInfo.fs
Normal file
@@ -0,0 +1,6 @@
|
||||
module AssemblyInfo
|
||||
|
||||
open System.Runtime.CompilerServices
|
||||
|
||||
[<assembly: InternalsVisibleTo("FicroKanSharp.Test")>]
|
||||
do()
|
@@ -1,6 +1,6 @@
|
||||
namespace FicroKanSharp
|
||||
|
||||
type Variable = private | VariableCount of int
|
||||
type Variable = internal | VariableCount of int
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module private Variable =
|
||||
@@ -16,9 +16,10 @@ type Goal =
|
||||
| Disj of Goal * Goal
|
||||
| Conj of Goal * Goal
|
||||
| Fresh of (Variable -> Goal)
|
||||
| Delay of (unit -> Goal)
|
||||
|
||||
type State =
|
||||
private
|
||||
internal
|
||||
{
|
||||
Substitution : Map<Variable, Term>
|
||||
VariableCounter : Variable
|
||||
@@ -56,11 +57,19 @@ module Stream =
|
||||
| Stream.Nonempty (fst, rest) ->
|
||||
mplus (g fst) (bind rest g)
|
||||
|
||||
let rec peel (s : Stream) : (Map<Variable, Term> * Stream) option =
|
||||
match s with
|
||||
| Stream.Empty -> None
|
||||
| Stream.Nonempty (fst, rest) -> Some (fst.Substitution, rest)
|
||||
| Stream.Procedure p -> peel (p ())
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Goal =
|
||||
let callFresh (f : Variable -> Goal) =
|
||||
Goal.Fresh f
|
||||
|
||||
let delay g = Goal.Delay g
|
||||
|
||||
let disj (goal1 : Goal) (goal2 : Goal) : Goal =
|
||||
Goal.Disj (goal1, goal2)
|
||||
|
||||
@@ -117,4 +126,6 @@ module Goal =
|
||||
| Goal.Disj (goal1, goal2) ->
|
||||
Stream.mplus (evaluate goal1 state) (evaluate goal2 state)
|
||||
| Goal.Conj (goal1, goal2) ->
|
||||
Stream.bind (evaluate goal1 state) (evaluate goal2)
|
||||
Stream.bind (evaluate goal1 state) (evaluate goal2)
|
||||
| Goal.Delay g ->
|
||||
Stream.Procedure (fun () -> evaluate (g ()) state)
|
@@ -7,6 +7,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Domain.fs" />
|
||||
<Compile Include="AssemblyInfo.fs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
Reference in New Issue
Block a user