F#-重载函数

F#-重载函数,f#,F#,有没有办法让函数重载 让我们看看这3个函数: // Returns StringPropertyInfo let stringProperty (expr:Expr<'a -> string>) (cfg:EntityInfo<'a>) = cfg.Property expr // Returns DatePropertyInfo let dateProperty (expr:Expr<'a -> System.DateTime>) (

有没有办法让函数重载

让我们看看这3个函数:

// 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

如果不是的话,完成类似的事情最简单的方法是什么?

我认为一个受歧视的联盟是你的朋友。在这种情况下,你会有这样的想法

type PropertyInfo = 
| StringPropertyInfo of string
| DatePropertyInfo of System.DateTime
| BytePropertyInfo of byte

然后匹配它,并在一个函数中执行适当的操作返回union…

简短回答,不。还有另一个问题与此相关

但是,您可以在类等中重载方法,否则.NET集成将无法很好地工作。这是一个可能的解决方案,尽管在我看来不是,一个很好的解决方案

您可以将它们放在不同的子模块中


也许您可以创建一个泛型函数,并通过其中一个参数确定返回类型。但是,对于类型推断,我是个新手,不能肯定地说。

如果你想使用基于歧视联合的方法,那么我认为声明更合适(因为你不需要使用引号)。Alex建议的类型的轻微修改如下:

type PropertyInfo<'a> =
  | String of Expr<'a -> string>
  | Date of Expr<'a -> System.DateTime>
  | ...
然后你会写:

cfg |> EF.property <@ e -> e.Foo @>
cfg|>EF.property e.Foo@>
最后,您还可以通过使函数完全泛型并进行动态类型测试(以决定使用何种返回类型),使其更简单(但不那么安全)。比如:

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

cfg |> property (String <@ fun e -> e.Foo @>)
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
let property<'a, 'r> (e:Expr<'a -> 'r>) (cfg:EntityInfo<'a>) =
  if typeof<'r> = typeof<string> then
    // ...
let属性(e:Expr)(cfg:EntityInfo=typeof then
// ...

要想得到你想要的东西,一种半丑陋的方法是对它进行一点概括并使用:

let inline property expr cfg =
    (^t : (member Property : Expr<'a -> 'b> -> 'c)(cfg, expr))
让内联属性expr cfg=
(^t:(成员属性:Expr->'c)(cfg,Expr))

但是,这可以应用于除
entityinfo之外的其他类型的值。我认为这不容易使用。使用此区分联合,您必须明确地使用
。-但是,似乎您无法在区分联合中定义泛型?至少
|字符串Expr@ebb:那是我的错误-更新的答案ld工作(类型
PropertyInfo
本身需要是泛型的-这样它里面就可以有一个类型变量
'a
)。我明白了。但是,它看起来不是一个可行的选项,因为我想重载的类型变量将返回不同的对象。
let inline property expr cfg =
    (^t : (member Property : Expr<'a -> 'b> -> 'c)(cfg, expr))