Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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<???, ???>()
like image 880
Ray Avatar asked Jun 01 '16 20:06

Ray


Video Answer


2 Answers

type T() =
    interface seq<T> with
        member this.GetEnumerator() = ([] :> seq<T>).GetEnumerator()
        member this.GetEnumerator() = ([] :> seq<T>).GetEnumerator() :> System.Collections.IEnumerator

let z = new Something<string, T>()
like image 123
kvb Avatar answered Sep 22 '22 12:09

kvb


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
like image 37
Mark Seemann Avatar answered Sep 19 '22 12:09

Mark Seemann