Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics 在泛型上与F#编译器斗争:类型';T与类型Foo1不匹配_Generics_F# - Fatal编程技术网

Generics 在泛型上与F#编译器斗争:类型';T与类型Foo1不匹配

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)

因此,我有一种简单的算法来读取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) =
    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