函数重载,静态类型继承和接口类型

时间:2018-07-25 13:51:03

标签: f#

(这种情况似乎没有被先前的线程回答,或者至少对我来说不是显而易见的,关键的区别是对高阶类型的递归要求)

(我已经重写了这个问题,以期给出一些行之有效的方法……但很痛苦……而不是对约束的含糊追求)

我有一些类似这样的代码(但是类型很多)...

type TypeOfOperator = 
    static member typeOf(i : TypeOf<int>) = 1
    static member typeOf(i : TypeOf<string>) = 2
    static member typeOf(i : TypeOf<seq<int>>) = 3 + TypeOfOperator.typeOf(TypeOf<int>())
    static member typeOf(i : TypeOf<seq<string>>) = 3 + TypeOfOperator.typeOf(TypeOf<string>())
    static member typeOf(i : TypeOf<option<int>>) = 4 + TypeOfOperator.typeOf(TypeOf<int>())
    static member typeOf(i : TypeOf<option<string>>) = 4 + TypeOfOperator.typeOf(TypeOf<string>())

let x = TypeOfOperator.typeOf(TypeOf<int>())
let y = TypeOfOperator.typeOf(TypeOf<string>())
let z = TypeOfOperator.typeOf(TypeOf<seq<int>>())
let a = TypeOfOperator.typeOf(TypeOf<seq<string>>())

此代码有效!...对于原子类型(例如“ int”),这种构造是固有的,但是高阶类型(例如seq )的形式化是公式化的...即常量“ +”对参数类型的一些递归调用。...但是,这似乎在F#中无法捕获,我不得不费力地手动实现代码。

理想情况下,option <>的方法将/应该实施一次,例如...

static member typeOf<'a>(i : TypeOf<option<'a>>) = 4 + TypeOfOperator.typeOf(TypeOf<'a>())

即写过一次...但这显然不能编译。

f#中是否可以实现上述方法/功能?

2 个答案:

答案 0 :(得分:0)

根据您在临近答案中显示的typeOf<'a>函数,有什么不同的方法呢?您是否考虑过这样的事情:

open System

let typeOf<'a> =
    match Type.GetTypeCode(typeof<'a>) with
    | TypeCode.Int32 -> 1
    | TypeCode.String -> 2
    | _ -> 0

这应该返回您所期望的:

typeOf<int> // 1
typeOf<string> // 2

如果您需要支持TypeCode中未列举的类型,则可以改用Type.GUID

答案 1 :(得分:0)

我已经做到了,它是基于先前的答案,但确实需要额外的痛苦。

这是实际的代码(因此返回类型arent ints不再...但是希望其他类型也能获得成功)

type T = T with
    static member typeOf(T,i : TypeOf<string>) : IType<string> = stringType()
    static member typeOf(T,i : TypeOf<int>) : IType<int> = intType()
    static member inline typeOf(T,t : TypeOf<seq< ^N >>) : IType<seq< ^N >> = seqType ((^T or ^N) : (static member typeOf: ^T * TypeOf< ^N > -> _) T, TypeOf< ^N >())
    static member inline typeOf(T,t : TypeOf<Option< ^N >>) : IType<Option< ^N >> = optionType ((^T or ^N) : (static member typeOf: ^T * TypeOf< ^N > -> _) T, TypeOf< ^N >())
    static member inline typeOf() : IType< ^N > = ((^T or ^N) : (static member typeOf: ^T * TypeOf< ^N > -> _) T, TypeOf< ^N >())

前两行是如何处理递归调用的示例,这些递归调用将解构高阶类型以获取参数并基于此调用方法。

最终的typeof只是删除这个幻影(?)T参数的好方法,该参数用来欺凌类型推断引擎,使其在正确的位置查找。

现在我们可以致电...

let x = T.typeOf<seq<string>>()