【问题标题】:F# and duck-typingF# 和鸭式打字
【发布时间】:2011-10-27 07:31:37
【问题描述】:

假设我在 F# 中定义了以下两种类型:

type Dog = { DogName:string; Age:int }
type Cat = { CatName:string; Age:int }

我期待以下方法适用于猫和狗:

let isOld x = x.Age >= 65

实际上,似乎发生的事情是isOld 只会接受猫:

let dog = { DogName = "Jackie"; Age = 4 }
let cat = { CatName = "Micky"; Age = 80 }

let isDogOld = isOld dog //error

我希望 F# 足够聪明,可以为猫和狗定义某种“虚拟”接口 X,以便 isOld 接受 X 作为参数,而不是 Cat

这不是 F# 在任何情况下都可以处理的事情,对吗?似乎 F# 类型推断系统不会做任何事情,而不是 C# 对 var 类型变量所做的事情。

【问题讨论】:

  • 无处不在!这是一个错字。
  • 您对编译器提出了很多要求,但 Google Go 可以满足您的要求,尽管函数签名不会是隐式的,但类型签名会。
  • 您要求的是结构类型。

标签: .net f# functional-programming type-inference duck-typing


【解决方案1】:

您可以使用成员约束定义 inline 函数,或者采用经典路线并使用接口(在这种情况下可能会首选)。

let inline isOld (x:^T) = (^T : (member Age : int) x) >= 65

编辑

我只记得这不适用于记录类型。从技术上讲,它们的成员是字段,尽管您可以使用 with member ... 与成员一起修改它们。无论如何,您都必须这样做才能满足接口。

作为参考,以下是您将如何实现具有记录类型的接口:

type IAging =
  abstract Age : int

type Dog = 
  { DogName : string
    Age : int } 
  interface IAging with
    member this.Age = //could also be `this.Age = this.Age`
      let { DogName = _; Age = age } = this
      age

【讨论】:

    【解决方案2】:

    FSharp.Interop.Dynamic(在 nuget 上)提供基于 DLR 的动态运算符实现(真正的动态鸭子类型)

    let isOld x = x?Age >= 65
    

    【讨论】:

    • 它似乎依赖运行时来做到这一点。起初我正在寻找的是一种静态推断方式。
    【解决方案3】:

    通常 F# 的鸭子类型是指编译时多态性。语法有点奇怪,但您应该可以从以下示例中解决它 -

    module DuckTyping
    
    // Demonstrates F#'s compile-time duck-typing.
    
    type RedDuck =
        { Name : string }
        member this.Quack () = "Red"
    
    type BlueDuck =
        { Name : string }
        member this.Quack () = "Blue"
    
    let inline name this =
        (^a : (member Name : string) this)
    
    let inline quack this =
        (^a : (member Quack : unit -> string) this)
    
    let howard = name { RedDuck.Name = "Howard" }
    let bob = name { BlueDuck.Name = "Bob" }
    let red = quack { RedDuck.Name = "Jim" }
    let blue = quack { BlueDuck.Name = "Fred" }
    

    请记住,这种多态性仅在编译时有效!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-25
      • 2013-03-02
      • 2015-08-01
      • 2011-09-28
      • 2012-10-26
      • 2011-03-23
      • 2011-05-11
      • 2020-02-13
      相关资源
      最近更新 更多