Generics 在泛型上与F#编译器斗争:类型';T与类型Foo1不匹配
因此,我有一种简单的算法来读取JSON文件,根据序列化是否有效,对结果进行处理:Generics 在泛型上与F#编译器斗争:类型';T与类型Foo1不匹配,generics,f#,Generics,F#,因此,我有一种简单的算法来读取JSON文件,根据序列化是否有效,对结果进行处理: namespace Test type IFoo = abstract member SomeFoo: string with get type Foo<'T when 'T :> IFoo> = { Bar: 'T; Baz: string; } type Foo1(someFoo: string, otherFoo: string)
namespace Test
type IFoo =
abstract member SomeFoo: string with get
type Foo<'T when 'T :> IFoo> =
{
Bar: 'T;
Baz: string;
}
type Foo1(someFoo: string, otherFoo: string) =
member val OtherFoo = otherFoo with get
interface IFoo with
member val SomeFoo = someFoo with get
type Foo2(someFoo: int, otherFoo: string) =
member val OtherFoo = otherFoo with get
interface IFoo with
member val SomeFoo = (someFoo + someFoo).ToString() with get
module TestModule =
let Deserialize<'T when 'T:> IFoo>(): Option<Foo<'T>> =
let json = System.IO.File.ReadAllText("someFile.json")
let foo1:Option<Foo<Foo1>> =
try
Some(Newtonsoft.Json.JsonConvert.DeserializeObject<Foo<Foo1>> json)
with
| _ -> None
match foo1 with
| Some(theFoo1) -> Some(theFoo1)
| None ->
let foo2:Option<Foo<Foo2>> =
try
Some(Newtonsoft.Json.JsonConvert.DeserializeObject<Foo<Foo2>> json)
with
| _ -> None
match foo2 with
| Some(theFoo2) -> Some(theFoo2:>Foo<IFoo>)
| None ->
System.Console.Error.WriteLine("No serialization format matched")
None
let DoStuff<'T when 'T:> IFoo>(foo: Foo<'T>): unit =
System.Console.WriteLine(foo.Bar.SomeFoo)
let Start() =
let readFoo = Deserialize()
if (readFoo.IsSome) then
DoStuff(readFoo.Value)
名称空间测试
类型IFoo=
抽象成员SomeFoo:get的字符串
输入Foo-IFoo>=
{
酒吧:T;
Baz:字符串;
}
输入Foo1(someFoo:string,otherFoo:string)=
成员val OtherFoo=OtherFoo和get
接口IFoo与
成员val SomeFoo=SomeFoo和get
输入Foo2(someFoo:int,otherFoo:string)=
成员val OtherFoo=OtherFoo和get
接口IFoo与
成员val SomeFoo=(SomeFoo+SomeFoo).ToString()和get
模块测试模块=
让我们反序列化IFoo>():选项):单位=
System.Console.WriteLine(foo.Bar.SomeFoo)
让我们开始=
让readFoo=反序列化()
如果(readFoo.IsSome)那么
DoStuff(readFoo.Value)
如您所见,有两种可能的类型:Foo1和Foo2。它们都实现了接口IFoo。因此,我的期望是,如果我声明一个方法来接收泛型约束IFoo>
,并返回Foo,但给定一个Foo。类型
“T”与类型“Foo1”不匹配
即使试图将其转换为Foo,编译器也不喜欢它,就像Some(theFoo2:>Foo)
:
类型“IFoo”与类型“t”不匹配
我如何正确地抽象它(显然,不使用对象
作为返回类型)?泛型的意思是“使用任何类型”
当您声明如下函数时:
let Deserialize<'T when 'T:> IFoo>(): Option<Foo<'T>>
然后,在构建值时不要忘记对其进行强制转换:
match foo1 with
| Some { Bar = foo1, Baz = baz } -> Some { Bar = foo1 :> IFoo, Baz = baz }
是的,您必须打开并重新包装该记录才能正常工作,因为尽管有外观,但这些记录的类型不同:左侧为Foo
,右侧为Foo
其次,如果您确实想保留Foo的具体类型,但又想根据其运行方式返回不同的类型,那么您别无选择,只能返回选择类型:
type DeserializationResult =
| One of Option<Foo<Foo1>>
| Two of Option<Foo<Foo2>>
let Deserialize(): DeserializationResult
现在我同意了第一个提议的解决方案,谢谢,尽管不断地包装和拆开是非常难看的。。。事实上,现在如何确保其他方法收到Foo
type DeserializationResult =
| One of Option<Foo<Foo1>>
| Two of Option<Foo<Foo2>>
let Deserialize(): DeserializationResult
match foo1 with
| Some _ -> One foo1