mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-05 20:18:43 +00:00
Absolute bare-bones support for generics in cata (#101)
This commit is contained in:
@@ -8,17 +8,17 @@ open FsCheck
|
||||
|
||||
[<TestFixture>]
|
||||
module TestCataGenerator =
|
||||
let idCata : TreeCata<_, _> =
|
||||
let idCata<'a, 'b> : TreeCata<'a, 'b, _, _> =
|
||||
{
|
||||
Tree =
|
||||
{ new TreeCataCase<_, _> with
|
||||
member _.Const x = Const x
|
||||
{ new TreeCataCase<_, _, _, _> with
|
||||
member _.Const x y = Const (x, y)
|
||||
member _.Pair x y z = Pair (x, y, z)
|
||||
member _.Sequential xs = Sequential xs
|
||||
member _.Builder x b = Builder (x, b)
|
||||
}
|
||||
TreeBuilder =
|
||||
{ new TreeBuilderCataCase<_, _> with
|
||||
{ new TreeBuilderCataCase<_, _, _, _> with
|
||||
member _.Child x = Child x
|
||||
member _.Parent x = Parent x
|
||||
}
|
||||
@@ -27,7 +27,7 @@ module TestCataGenerator =
|
||||
[<Test>]
|
||||
let ``Example`` () =
|
||||
let x =
|
||||
Tree.Pair (Tree.Const (Const.Int 0), Tree.Const (Const.String ""), PairOpKind.ThenDoSeq)
|
||||
Tree.Pair (Tree.Const (Const.Verbatim 0, "hi"), Tree.Const (Const.String "", "bye"), PairOpKind.ThenDoSeq)
|
||||
|
||||
TreeCata.runTree idCata x |> shouldEqual x
|
||||
|
||||
@@ -36,7 +36,7 @@ module TestCataGenerator =
|
||||
let ``Cata works`` () =
|
||||
let builderCases = ref 0
|
||||
|
||||
let property (x : Tree) =
|
||||
let property (x : Tree<int, string>) =
|
||||
match x with
|
||||
| Tree.Builder _ -> Interlocked.Increment builderCases |> ignore
|
||||
| _ -> ()
|
||||
|
@@ -8,10 +8,10 @@ open ConsumePlugin
|
||||
[<TestFixture>]
|
||||
module TestMyList =
|
||||
|
||||
let idCata : MyListCata<_> =
|
||||
let idCata<'a> : MyListCata<'a, _> =
|
||||
{
|
||||
MyList =
|
||||
{ new MyListCataCase<_> with
|
||||
{ new MyListCataCase<'a, _> with
|
||||
member _.Nil = MyList.Nil
|
||||
|
||||
member _.Cons head tail =
|
||||
@@ -21,36 +21,32 @@ module TestMyList =
|
||||
Tail = tail
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[<Test>]
|
||||
let ``Cata works`` () =
|
||||
let property (x : MyList) = MyListCata.runMyList idCata x = x
|
||||
let property (x : MyList<int>) = MyListCata.runMyList idCata x = x
|
||||
|
||||
Check.QuickThrowOnFailure property
|
||||
|
||||
let toListCata =
|
||||
let toListCata<'a> =
|
||||
{
|
||||
MyList =
|
||||
{ new MyListCataCase<int list> with
|
||||
{ new MyListCataCase<'a, 'a list> with
|
||||
member _.Nil = []
|
||||
member _.Cons (head : int) (tail : int list) = head :: tail
|
||||
member _.Cons (head : 'a) (tail : 'a list) = head :: tail
|
||||
}
|
||||
}
|
||||
|
||||
let toListViaCata (l : MyList) : int list = MyListCata.runMyList toListCata l
|
||||
let toListViaCata<'a> (l : MyList<'a>) : 'a list = MyListCata.runMyList toListCata l
|
||||
|
||||
|
||||
[<Test>]
|
||||
let ``Example of a fold converting to a new data structure`` () =
|
||||
let rec toListNaive (l : MyList) : int list =
|
||||
let rec toListNaive (l : MyList<int>) : int list =
|
||||
match l with
|
||||
| MyList.Nil -> []
|
||||
| MyList.Cons {
|
||||
Head = head
|
||||
Tail = tail
|
||||
} -> head :: toListNaive tail
|
||||
| MyList.Cons consCell -> consCell.Head :: toListNaive consCell.Tail
|
||||
|
||||
Check.QuickThrowOnFailure (fun l -> toListNaive l = toListViaCata l)
|
||||
|
||||
@@ -62,20 +58,20 @@ module TestMyList =
|
||||
let sumCata =
|
||||
{
|
||||
MyList =
|
||||
{ new MyListCataCase<int64> with
|
||||
{ new MyListCataCase<int, int64> with
|
||||
member _.Nil = baseCase
|
||||
member _.Cons (head : int) (tail : int64) = atLeaf head tail
|
||||
}
|
||||
}
|
||||
|
||||
let viaCata (l : MyList) : int64 = MyListCata.runMyList sumCata l
|
||||
let viaCata (l : MyList<int>) : int64 = MyListCata.runMyList sumCata l
|
||||
|
||||
let viaFold (l : MyList) : int64 =
|
||||
let viaFold (l : MyList<int>) : int64 =
|
||||
// choose your favourite "to list" method - here I use the cata
|
||||
// but that could have been done naively
|
||||
(toListViaCata l, baseCase)
|
||||
||> List.foldBack (fun elt state -> atLeaf elt state)
|
||||
|
||||
let property (l : MyList) = viaCata l = viaFold l
|
||||
let property (l : MyList<int>) = viaCata l = viaFold l
|
||||
|
||||
Check.QuickThrowOnFailure property
|
||||
|
@@ -8,19 +8,18 @@ open ConsumePlugin
|
||||
[<TestFixture>]
|
||||
module TestMyList2 =
|
||||
|
||||
let idCata : MyList2Cata<_> =
|
||||
let idCata<'a> : MyList2Cata<'a, _> =
|
||||
{
|
||||
MyList2 =
|
||||
{ new MyList2CataCase<_> with
|
||||
{ new MyList2CataCase<'a, _> with
|
||||
member _.Nil = MyList2.Nil
|
||||
|
||||
member _.Cons head tail = MyList2.Cons (head, tail)
|
||||
member _.Cons (head : 'a) (tail : MyList2<'a>) = MyList2.Cons (head, tail)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[<Test>]
|
||||
let ``Cata works`` () =
|
||||
let property (x : MyList2) = MyList2Cata.runMyList2 idCata x = x
|
||||
let property (x : MyList2<int>) = MyList2Cata.runMyList2 idCata x = x
|
||||
|
||||
Check.QuickThrowOnFailure property
|
||||
|
Reference in New Issue
Block a user