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>) (cfg:EntityInfo<'a>) = 
    cfg.Property expr

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

有没有办法将它们全部合并为:

let property expr cfg = ....

如果没有,完成类似事情的最巧妙的方法是什么?

最佳答案

如果您想使用基于受歧视联合的方法,那么我认为声明更合适(因为您不需要使用引号进行操作)。对 Alex 建议的类型稍作修改是:

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

然后你会写这样的内容:

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

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

另一种选择是将 property 实现为类型的静态成员,在这种情况下,您可以使用常用的重载(类似于 C#)。像这样的东西:

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

然后你会写:

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

最后,您还可以通过使函数完全通用并进行动态类型测试(以决定使用什么返回类型)来使其变得更简单(但不太安全)。像这样的东西:

let property<'a, 'r> (e:Expr<'a -> 'r>) (cfg:EntityInfo<'a>) =
  if typeof<'r> = typeof<string> then
    // ...

关于F# - 重载函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5745172/

相关文章:

f# - 当嵌套是可选的时,嵌套 f# 函数与不嵌套它们有何不同?

performance - F# 似乎比其他语言慢...我能做些什么来加快速度?

.net - F# 和自动向上转换 : sometimes it does, 有时不会,这背后的基本原理是什么?

asp.net-web-api - 我无法在本地主机上使用 Android 模拟器的类型提供程序

types - 与文字的可区分联合

mongodb - f# 使用记录插入 MongoDB

f# - 如何做 Seq.unzip

f# - 使用 F# 类型提供程序如何实现基本构造函数调用作为构造函数定义的一部分

configuration - 从 F# 脚本使用 app.config

f# - 具有重复元素的无限序列