Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# - Overload Functions

Tags:

f#

Is there a way to do somehow overload a function?

Let's take those 3 functions:

// Returns StringPropertyInfo
let stringProperty (expr:Expr<'a -> string>) (cfg:EntityInfo<'a>) = 
    cfg.Property expr

// Returns DatePropertyInfo
let dateProperty (expr:Expr<'a -> System.DateTime>) (cfg:EntityInfo<'a>) = 
    cfg.Property expr

// Returns BytePropertyInfo
let byteProperty (expr:Expr<'a -> System.Byte>) (cfg:EntityInfo<'a>) =
     cfg.Property expr

is there a way to merge them all into just:

let property expr cfg = ....

if not, whats the most neat way to accomplish something similar?

like image 216
ebb Avatar asked Apr 21 '11 14:04

ebb


2 Answers

If you want to use an approach based on discriminated unions, then I think the declaration is more suitable (as you don't need to manipulate with quotations). Slight modification of the type suggested by Alex is:

type PropertyInfo<'a> =
  | String of Expr<'a -> string>
  | Date of Expr<'a -> System.DateTime>
  | ...

Then you'd write something like:

let property (pi:PropertyInfo<'a>) (cfg:EntityInfo<'a>) =
  match pi with
  | String e -> cfg.Property e
  | ...

cfg |> property (String <@ fun e -> e.Foo @>)

Another option would be to implement property as a static member of a type, in which case you can use usual overloading (similar to C#). Something like:

type EF = 
  static member property (expr:Expr<'a -> string>) (cfg:EntityInfo<'a>) = 
    cfg.Property expr
  static member property (expr:Expr<'a -> System.DateTime>) (cfg:EntityInfo<'a>) = 
    cfg.Property expr
  static member property (expr:Expr<'a -> System.Byte>) (cfg:EntityInfo<'a>) =
     cfg.Property expr

Then you'd write:

cfg |> EF.property <@ e -> e.Foo @>

Finally, you could also make it a bit simpler (but less safer) by making the function fully generic and doing dynamic type test (to decide what return type is used). Something like:

let property<'a, 'r> (e:Expr<'a -> 'r>) (cfg:EntityInfo<'a>) =
  if typeof<'r> = typeof<string> then
    // ...
like image 81
Tomas Petricek Avatar answered Sep 30 '22 15:09

Tomas Petricek


Short answer, no. There's another question dealing with this here.

You can however overload methods in classes etc. otherwise the .NET integration wouldn't work too well. This is one possible solution albeit not in my eyes, a pretty one.

You could put them in different sub-modules.

Perhaps you could make a generic function and decide the return type through one of the parameters. I'm too much of a newbie when it comes to the type inference to say for certain though.

like image 36
Skurmedel Avatar answered Sep 30 '22 15:09

Skurmedel