F#-重载函数
有没有办法让函数重载 让我们看看这3个函数: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>) (
// 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))