F#泛型函数类型约束问题:如何为IsA函数添加子类型约束
为F#泛型类型转换函数添加类型约束的方案
你可以通过添加引用类型约束和子类型关系约束,让这个泛型函数更安全且符合类型转换逻辑,无需为每个子类型单独编写函数。
修改后的泛型函数(带约束)
let IsA<'item, 'input when 'item : not struct and 'input : not struct and 'item :> 'input> (subject: 'input) = match subject with | :? 'item as item -> Some item | _ -> None
约束说明
'item : not struct和'input : not struct:确保两个类型都是引用类型,因为F#的:?类型测试操作符仅对引用类型(和可空值类型)有效,值类型之间的向下转换无意义,加这个约束可以避免无效调用。'item :> 'input:明确'item是'input的子类型(或同一类型),保证类型转换在逻辑上是合理的,比如避免出现尝试把string转成int这种无意义的操作。
使用示例
先定义基础类和子类:
type Animal() = class end type Dog() = inherit Animal() type Cat() = inherit Animal()
调用泛型函数:
let animal: Animal = Dog() // 转换为Dog类型,返回Some<Dog> let dogOpt = IsA<Dog, Animal> animal // 尝试转换为Cat类型,返回None let catOpt = IsA<Cat, Animal> animal
简化版(接受obj类型参数)
如果你的场景中经常从obj类型转换到具体子类型,可以进一步简化约束,省略'input泛型参数:
let IsA<'item when 'item : not struct> (subject: obj) = match subject with | :? 'item as item -> Some item | _ -> None
调用时更简洁:
let dogOpt = IsA<Dog> animal
内容的提问来源于stack exchange,提问作者kam
相关产品推荐
相关产品推荐

