Jack Fox
Jack Fox

Reputation: 945

Can an input parameter of an abstract type member be constrained in F#?

Taking the idea of phantom types explained in this post Implementing phantom types in F# , I'm trying to constrain the input parameter of an abstract type member, and more generally any type member. This may be impossible, and I'm happy to get that message.

Here is what I am attempting:

// my phantom type
type Ascending = interface end
type Descending = interface end
type HeapOrder =
    inherit Ascending
    inherit Descending

// my type
type IHeap<'a when 'a : comparison> =
    inherit System.Collections.IEnumerable
    inherit System.Collections.Generic.IEnumerable<'a>
...
abstract member Order : HeapOrder with get
...
// ...and one or the other of these inherited types :
type IHeap<'c, 'a when 'c :> IHeap<'c, 'a> and 'a : comparison> =
    inherit IHeap<'a>
// or:
type IHeap<'a, 'd when 'a : comparison  and 'd :> HeapOrder> =
    inherit System.Collections.IEnumerable
    inherit System.Collections.Generic.IEnumerable<'a>

type IHeap<'c, 'a, 'd when 'c :> IHeap<'c, 'a, 'd> and 'a : comparison and 'd :> HeapOrder> =
    inherit IHeap<'a>
...
// ...and the member I want to constrain, so that the HeapOrder of the 
// input parameter matches the HeapOrder of the instantiated type.
// Conceptually one of these alternatives (none of these build, 
// but they should convey what I'm attempting):
//
abstract member Merge : ('c when 'c<'c, 'a> : (member Order when Order :> 'd))
// or
abstract member Merge : ('c when c' :> IHeap<'c, 'a, 'd>) -> 'c
// or
abstract member Merge : ('c when c' : #IHeap<'c, 'a, 'd>) -> 'c

Upvotes: 2

Views: 211

Answers (1)

Kurt Schelfthout
Kurt Schelfthout

Reputation: 8980

You can't further constrain a class type parameter for a particular member, if that's what you're asking. You can introduce a new member type parameter that is independently constrained, if you like. I am not sure whether that solves your problem.

I think both Ascending and Descending should inherit from HeapOrder, instead of the other way around.

Then you can instantiate a heap with either Ascending or Descending, and the 'd should capture that fact so you can't Merge with another one with a different HeapOrder. I don't think you need separate constraints on Merge for that.

Just in case, you can constrain type parameters of abstract members by putting the when at the end. Also you have a typo in your 'c in the last two merges, the ' comes after the c.

Upvotes: 1

Related Questions