F# 和鸭子类型 [英] F# and duck-typing

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

问题描述

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

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

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

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

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

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.

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

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.

推荐答案

你可以定义一个带有成员约束的 inline 函数,或者走经典路线并使用接口(这可能是首选在这种情况下).

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

编辑

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

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天全站免登陆