F# type constrains subtyping

65 Views Asked by At

I got a question, mostly because I found a case where classes and subtyping was needed.

let say we got some function

let IsA<'item, 'input> (subject: 'input) = 
    match subject with
    | :? 'item as item -> Some item
    | _ -> None

is there a way to constraint the generic types to allow this.

The alternative is to do a IsA function for all subtype constrains.

This is a dummy case, but it clearly describes what I need to do.

1

There are 1 best solutions below

4
Tomas Petricek On BEST ANSWER

I'm not exactly sure what your motivation here is. You can certainly box the subject before pattern matching on the value:

let IsA<'item, 'input> (subject: 'input) = 
    match box subject with
    | :? 'item as item -> Some item
    | _ -> None

This lets you call IsA on various things, including the ones that make sense (but also, because of the boxing, some that cannot possibly make sense). You need to constrain the 'item type parameter, either by explicitly saying IsA<Cat, _> or by having an annotation elsewhere:

type Animal() = class end
type Dog() = inherit Animal()
type Cat() = inherit Animal()
let dogAnimal = Dog() :> Animal

let asCat : Cat option = IsA dogAnimal
let asDog : Dog option = IsA dogAnimal
let asCat2 : Cat option = IsA (System.Random())

In principlie, it would be nice if the last case with Random was not allowed. Unfortunately, you cannot specify a constraint for this though. The following does not work:

let IsA<'item, 'input when 'item :> 'input> (subject: 'input) = 
    match subject with
    | :? 'item as item -> Some item
    | _ -> None

The issue is discussed, for example, here: How to constrain one type parameter by another

Related Questions in F#