gpt4 book ai didi

f# - 实现具有带有泛型类型参数的方法的 F# 接口(interface)类型

转载 作者:行者123 更新时间:2023-12-01 23:34:48 26 4
gpt4 key购买 nike

Use interfaces to group related operations F# 组件设计指南的一部分,它列出了具有带有泛型类型参数的方法的接口(interface)类型,'T .

type Serializer =
abstract Serialize<'T> : preserveRefEq: bool -> value: 'T -> string
abstract Deserialize<'T> : preserveRefEq: bool -> pickle: string -> 'T

object expressions引用部分和 interfaces引用部分没有列出任何如何使用通用接口(interface)实现接口(interface)的示例 'T范围。 Generics引用部分在该部分的末尾有一个简短的示例...我仍然难以编写反射(reflect)该示例的代码。

我知道如何实现具有泛型类型的接口(interface),只是不知道如何实现具有泛型类型参数的接口(interface)。

这是一个简单的玩具示例,我一直在尝试实现以了解如何执行此操作:

type Foo = Foo of string
type Bar = Bar of string

let unwrapFoo (Foo foo) = foo
let unwrapBar (Bar bar) = bar

type IWrapper =
abstract member Unwrap<'T> : 'T -> string
abstract member Wrap<'U> : string -> 'U

尝试实现 IWrapper是我遇到编译器错误的地方:

let wrapper =
{ new IWrapper with
member this.Unwrap<Foo>(foo: Foo) = unwrapFoo foo
member this.Wrap<Bar> string = Bar string }

wrapper让绑定(bind)会返回一个编译器错误:Unexpected identifier in pattern. Expected infix operator, quote symbol or other token.

Unexpected identifier in pattern. Expected infix operator, quote symbol or other token.

我在实现 IWrapper 方面的其他尝试给我这个编译器错误:typecheck error The member 'Unwrap<'T> : Foo -> string' does not have the correct type to override the corresponding abstract method. The required signature is 'Unwrap<'T> : 'T -> string'.

let wrapper =
{ new IWrapper with
member this.Unwrap<'T>(foo: Foo) = unwrapFoo foo
member this.Wrap<'U> string = Bar(string) }

typecheck error The member 'Unwrap<'T> : Foo -> string' does not have the correct type to override the corresponding abstract method. The required signature is 'Unwrap<'T> : 'T -> string'.

非常感谢任何帮助实现此接口(interface)类型和阅读编译器错误消息(我确定正在向我解释如何解决我的问题)的洞察力。谢谢大家!

最佳答案

通用签名并不代表您认为的意思。

这并不意味着“我将采用一些类型作为参数。还不知道那个类型是什么,我稍后再决定,但现在我们称它为 'T 。”不是这个意思。

相反,它的意思是“选择一个类型,任何类型。我不知道你要选择什么,所以现在我们称它为 'T。选择类型了吗?好!现在我要该类型的参数"

换句话说,选择类型参数的是函数的调用者,而不是实现者。

与其他通用函数比较。我们以 List.length 为例。它具有以下签名:

List.length<'a> : 'a list -> int

这个签名说:“选择任何类型 'a。任何类型,我不在乎是哪个。然后我将获取类型 'a list 的列表并返回给你一个 int

它的实现者不能自由决定将某些特定列表作为参数 - 例如int list , - 不,他们必须以适用于任何类型的方式编写函数。因为这就是类型签名所 promise 的。

这意味着,如果您按照定义方式定义了 IWrapper 接口(interface),则方法必须能够接受任何 类型,而不仅仅是 FooBar 。因为这就是方法的类型签名所 promise 的。


但在我看来,您真正想做的是创建一个特定于类型的包装器。一个包装器,可以包装和解开某些特定的两种类型,而不仅仅是一般的任何类型。是这样吗?

如果是这样,那么类型参数应该在接口(interface)上,而不是在方法上:

type IWrapper<'T, 'U> =
abstract member Unwrap : 'T -> string
abstract member Wrap : string -> 'U

这个定义说“如果你自己有一个 IWrapper<a, b> 的实例,那么你可以用它来解包 a 或包装 b,没有别的

现在您可以专门为 FooBar 创建一个包装器:

let foobarWrapper =
{ new IWrapper<Foo, Bar> with
member this.Unwrap foo = unwrapFoo foo
member this.Wrap string = Bar string }

关于f# - 实现具有带有泛型类型参数的方法的 F# 接口(interface)类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65751331/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com