F#和鸭子打字 [英] F# and duck-typing

查看:93
本文介绍了F#和鸭子打字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  type Dog = {DogName:string;年龄:int} 
类型Cat = {CatName:string; Age:int}

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

  let isOld x = x.Age> = 65 

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

  let dog = {DogName =Jackie;年龄= 4} 
let cat = {CatName =Micky;年龄= 80}

让isDogOld = isOld dog //错误

我的希望F#能够聪明地为猫和狗定义某种虚拟接口 X ,这样 isOld 会接受X作为参数,而不是 Cat

这不是F#在任何情况下都能处理的事情,对吗?看起来F#类型推断系统不会做什么比C#用 var 类型变量做什么更多。

解决方案

您可以使用成员约束来定义 inline 函数,也可以使用经典路由并使用接口(这可能会首选

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



编辑



I只记得这不适用于记录类型。从技术上讲,他们的成员是领域,但您可以使用与成员...... 修改成员。您必须这样做才能满足界面。



作为参考,您将如何实现与记录类型的接口:

  type IAging = 
抽象年龄:int

类型Dog =
{DogName:string
Age:int}
接口IAng与
成员this.Age = //也可以是`this.Age = this.Age`
let {DogName = _;年龄=年龄=本次
年龄


Let's say I defined in F# the following two types:

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

I was expecting the following method to work for both cats and dogs:

let isOld x = x.Age >= 65

Actually, what seems to happen is that isOld will only accept cats:

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

let isDogOld = isOld dog //error

My hopes were that F# would be smart enough to define some kind of "virtual" interface X for both cats and dogs so that isOld would accept a X as argument, instead of a Cat.

This isn't something that F# will in any circumstance handle, am I right? It seems like F# type inference system would not do anything more than what the C# does with var typed variables.

解决方案

You can define an inline function with a member constraint, or go the classic route and use an interface (which would probably be preferred in this case).

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

EDIT

I just remembered this won't work for record types. Technically their members are fields, although you can amend them with members using with member .... You would have to do that to satisfy an interface anyway.

For reference, here's how you would implement an interface with a record type:

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

这篇关于F#和鸭子打字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆