Search code examples
typesf#type-constraintsrecursive-type

Impossible to make object with a recursive type constraint?


This is a purely academic question, but riffing off of this question about type constraints. The questioner gave this as an example:

type Something<'a, 'b when 'b :> seq<'b>>() =
    member __.x = 42

which f# happily compiles. Now the problem is how do you make this object??

let z = new Something<???, ???>()

Solution

  • Here's one way:

    open System.Collections.Generic
    
    type Node<'a> () =
        let getEmptyEnumerator () = Seq.empty<Node<'a>>.GetEnumerator ()
        interface IEnumerable<Node<'a>> with
            member this.GetEnumerator () = getEmptyEnumerator ()
            member this.GetEnumerator () =
                getEmptyEnumerator () :> System.Collections.IEnumerator
    

    Instead of returning the empty sequence, you could implement this class to return a sequence of child nodes. I called this type Node<'a>, because it's a fairly idiomatic way to model a tree (or a graph) in C#.

    Use:

    > let smth = Something<string, Node<int>> ();;    
    val smth : Something<string,Node<int>>
    
    > smth.x;;
    val it : int = 42