Alexander K.
Alexander K.

Reputation: 121

F# generic function

I have two types and their corresponding values. I'm attempting to come up with a generic function that adds values of either type. That is, a function that gets two values of the same type and adds them. For example, MyInt 7 and MyInt 13 should output MyInt 20. The function won't work. What am I doing wrong here?

type MyInt = MyInt of int
let xInt = MyInt 7
let yInt = MyInt 13

type MyDec = MyDec of decimal
let xDec = MyDec 7.0M
let yDec = MyDec 13.0M

let add<'a> (x:'a) (y:'a) : 'a  = 
    let ('a innerX) = x     // unwrap the inner value
    let ('a innerY) = y     // unwrap the inner value
    'a (innerX + innerY)    // add the inner values and then wrap the result

Upvotes: 0

Views: 44

Answers (1)

Brian Berns
Brian Berns

Reputation: 17123

There are a couple of issues here. The first is that the MyInt constructor is different from the MyInt type, even though they look identical. Let's clarify that by using MakeMyInt as the constructor name instead:

type MyInt = MakeMyInt of int
type MyDec = MakeMyDec of decimal

You cannot construct or destruct a union value using a type name (e.g. MyInt) or type parameter, ('a). You have to use a constructor (e.g. MakeMyInt).

Now, if you want to be able to add instances of your types, the best approach is to create a static addition member for each:

type MyInt =
    MakeMyInt of int
        static member (+)(MakeMyInt x, MakeMyInt y) =
            MakeMyInt (x + y)

type MyDec =
    MakeMyDec of decimal
        static member (+)(MakeMyDec x, MakeMyDec y) =
            MakeMyDec (x + y)

With those in place you can add instances of both types directly:

printfn $"{xInt + yInt}"   // MakeMyInt 20
printfn $"{xDec + yDec}"   // MakeMyDec 20.0M

No generic addition function is needed.

Upvotes: 3

Related Questions