如何在接口实现中保留未实现的泛型类型参数?

时间:2017-05-18 14:51:33

标签: generics f#

假设我有以下通用接口

type IStorageX<'a, 'b> =
    abstract Make: 'a -> 'b
    abstract From: 'c -> 'b

以下两种类型

type SomeInput<'a> = {value : 'a}

type SomeThing = {value: string}
    with interface IStorageX<int, SomeThing> with
        member this.Make x = {value = sprintf "%A" x}    
        member this.From (x:SomeInput<'a>) = {value = sprintf "%A" x.value}    

如何让F#了解member From应该允许任何类型的输入(只要它是SomeInput)?

我在某种程度上试图尝试

type IStorageX<'a, 'b, 'c> =
    abstract Make: 'a -> 'b
    abstract From: 'c -> 'b

type SomeThing = {value: string}
    with interface IStorageX<int, SomeThing, SomeInput<'a>> with
                                                     //^^--- unrealized generic param here
        member this.Make x = {value = sprintf "%A" x}    
        member this.From x = {value = sprintf "%A" x.value}    

但是这也没有编译,因为我可能没有在未实现的接口上使用泛型类型参数。

我能做到的唯一方法就是这样

type SomeThing = {value: string}
    with interface IStorageX<int, SomeThing, SomeInput<int>> with
        member this.Make x = {value = sprintf "%A" x}    
        member this.From (x:SomeInput<'a>) = {value = sprintf "%A" x.value}    

即完全制定所有通用参数。这当然不起作用,因为我必须为每种类型的SomeInput实现它们......

关于如何做到这一点的任何想法?

THX

PS:我能够非常快速地使用SRTP定义解决方案。但是我想要一个基于接口的解决方案,因为SRTP在某种程度上是坏的,F#land中的每个人都喜欢&#34;不,不,不!讨厌的男孩!&#34;

1 个答案:

答案 0 :(得分:5)

对于您来说,从实施方面和消费者方面准确地包含您正在努力实现的内容的更多细节将非常有帮助 - 如果没有它很难推断出什么是最好的惯用的解决方案是。建立你的第二个例子,似乎你希望你能做的就是

type IStorageX<'a, 'b, 'c> =
    abstract Make: 'a -> 'b
    abstract From: 'c -> 'b

并让SomeThing类型为IStorageX<int, SomeThing, SomeInput<'a>>实施'a,但是无法做到这一点 - 类型无法实现{{1}在.NET类型系统中。但是,您可以提供一种方法,而不是实现接口:

forall 'a.I<'a>