The main problem is that F # does not allow you to say that 'a and 'b in the case of discriminatory combining are “parameters” of the data stored in this case. Some other languages support this (it is called generalized algebraic data types in Haskell), but there is the usual compromise that makes the language more complex.
You can actually emulate this in F #, but it is ugly - so I would think twice before going this route. The idea is that you can define an interface using a generic method that is called with appropriate arguments like 'a and 'b .
type Val<'T> = | Val of 'T | Func of IFunc<'T> and IFunc<'T> = abstract Invoke<'R> : IFuncOperation<'T, 'R> -> 'R and IFuncOperation<'T2, 'R> = abstract Invoke<'T1> : ('T1 -> 'T2) * Val<'T1> -> 'R
The value enclosed in Func can be specified by IFuncOperation and will call it with your 'a , which is an argument of the type of the general method - 'T1 in my name.
You can make the construction of values reasonably enjoyable:
let makeFunc fv = Func({ new IFunc<_> with member x.Invoke(op) = op.Invoke(f, v) }) let makeVal v = Val(v) let valString = makeFunc (fun n -> sprintf "Got: %d" n) (makeVal 42)
valString now represents the int -> string transformation applied to Val<int> .
The code you need to write for pattern matching on Func is pretty ugly though:
let rec eval<'T> (value:Val<'T>) : 'T = match value with | Val r -> r | Func f -> { new IFuncOperation<'T, 'T> with member x.Invoke<'S>(f, value:Val<'S>) = f (eval<'S> value) } |> f.Invoke eval valString
I used a similar pattern in some internal units of Deedle, but never in code that was even close to what end users would write. I think this is acceptable on a very well hidden inner level, but I would definitely not use it in what was often called.
Depending on your original problem, perhaps a more pleasant way - you can define a discriminated union of PrimitiveValue to store various primitive values that your calculation can do, or simply present operations using the interface - but it's hard to say which is better in your case, not knowing the context.