Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can I set a "is a Discriminated Union" type constraint on a generic argument in F# type declaration?

I am creating a type system for some generic types of common input:

// type Validator<'t> when 't :> ??? = Validator of 't
// with member x.validate value condition =
//         if condition then
//             (true, Some ('t value))
//         else
//             (false, None)

module Validatable =
    let validate t value condition =        
        if condition then
            (true, Some (t value))
        else
            (false, None)

type Email = Email of string
with member x.validate(s) = Validatable.validate Email s (Regex.IsMatch(s, ""))

type Name = Name of string
with member x.validate(s) = Validatable.validate Name s (Regex.IsMatch(s, ""))

type PhoneNumber = PhoneNumber of string
with member x.validate(s) = Validatable.validate PhoneNumber s (Regex.IsMatch(s, ""))

You’ll see that within the comment, I have another type commented out. I am hoping to use the type defined within the comment to replace the functionality of the validate t value condition function within the Validatable module.

What do I need to replace the ??? with to allow me to say that the generic parameter 't is the case identifier of a Discriminated Union?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

A union case isn’t a type, it’s a function that produces a value of type. So you can write your Validator type like this instead:

type Validator<'inp, 'out> = Validator of ('inp -> 'out)
with member x.validate value condition =
        let (Validator f) = x
        if condition then
            (true, Some (f value))
        else
            (false, None)

And use it like this:

type Email = Email of string
with member x.validate(s) = (Validator Email).validate s (Regex.IsMatch(s, ""))

type Name = Name of string
with member x.validate(s) = (Validator Name).validate s (Regex.IsMatch(s, ""))

type PhoneNumber = PhoneNumber of string
with member x.validate(s) = (Validator PhoneNumber).validate s (Regex.IsMatch(s, ""))
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading