I wanted to play with 2-3 finger trees, as described in the (Haskell) Hinze document (see also this blog ).
type Node<'a> = | Node2 of 'a * 'a | Node3 of 'a * 'a * 'a static member OfList = function | [a; b] -> Node2(a, b) | [a; b; c] -> Node3(a, b, c) | _ -> failwith "Only lists of length 2 or 3 accepted!" member me.ToList () = match me with | Node2(a, b) -> [a; b] | Node3(a, b, c) -> [a; b; c] type Digit<'a> = | One of 'a | Two of 'a * 'a | Three of 'a * 'a * 'a | Four of 'a * 'a * 'a * 'a static member OfList = function | [a] -> One(a) | [a; b] -> Two(a, b) | [a; b; c] -> Three(a, b, c) | [a; b; c; d] -> Four(a, b, c, d) | _ -> failwith "Only lists of length 1 to 4 accepted!" member me.ToList () = match me with | One a -> [a] | Two(a, b) -> [a; b] | Three(a, b, c) -> [a; b; c] | Four(a, b, c, d) -> [a; b; c; d] member me.Append x = match me with | One a -> Two(a, x) | Two(a, b) -> Three(a, b, x) | Three(a, b, c) -> Four(a, b, c, x) | _ -> failwith "Cannot prepend to Digit.Four!" member me.Prepend x = match me with | One a -> Two(x, a) | Two(a, b) -> Three(x, a, b) | Three(a, b, c) -> Four(x, a, b, c) | _ -> failwith "Cannot prepend to Digit.Four!" [<NoComparison>] [<NoEquality>] type FingerTree<'a> = | Empty | Single of 'a | Deep of Digit<'a> * FingerTree<Node<'a>> * Digit<'a> type Digit<'a> with member me.Promote () = match me with | One a -> Single a | Two(a, b) -> Deep(One a, Empty, One b) | Three(a, b, c) -> Deep(One a, Empty, Two(b, c)) | Four(a, b, c, d) -> Deep(Two(a, b), Empty, Two(c, d)) type View<'a> = Nil | View of 'a * FingerTree<'a>
Now I just can't get the viewl function viewl work, it complains about a type mismatch:
Waiting for FingerTree <'a>, but considering FingerTree>.
The resulting type would be infinite when combining '' a 'and' Node <'a>' FingerTree.
let rec viewl : FingerTree<'a> -> View<'a> = function | Empty -> Nil | Single x -> View(x, Empty) | Deep(One x, deeper(*:FingerTree<'a>/FingerTree<Node<'a>>*), suffix) -> let rest = match viewl deeper with | Nil -> suffix.Promote() | View (node(*:Node<'a>*), rest) -> let prefix = node.ToList() |> Digit<_>.OfList Deep(prefix, rest, suffix) View(x, rest) | Deep(prefix, deeper, suffix) -> match prefix.ToList() with | x::xs -> View(x, Deep(Digit<_>.OfList xs, deeper, suffix)) | _ -> failwith "Impossible!"
I had this error before in prepend , but I was able to resolve it by adding full information about the function.
For viewl this doesn't seem to be enough, so I also tried adding types in the middle of the function (look for comments). This did not work.
I understand the error and where it comes from. Can someone tell me how to do this? IMHO, this should be possible, because otherwise the prepend also not compile. Maybe a trick like this helps? (I don’t understand, though).
PS: I also put the FsSnip code to play in the browser.