首页 文章

F#是否了解其受歧视的工会的编制表格?

提问于
浏览
8

F#中的区分联合被编译为抽象类,其选项成为嵌套的具体类 .

type DU = A | B

DU是抽象的,而DU.A和DU.B是具体的 .

使用ServiceStack,可以使用函数自定义类型到JSON字符串和后面的序列化 . 关于DU类型,这是我在C#中如何做到的 .

using ServiceStack.Text;

JsConfig<DU.A>.SerializeFn = v => "A"; // Func<DU.A, String>
JsConfig<DU.B>.SerializeFn = v => "B"; // Func<DU.B, String>
JsConfig<DU>.DeserializeFn = s =>
    if s == "A" then DU.NewA() else DU.NewB(); // Func<String, DU>

F#是否了解其受歧视的工会的编制表格?如何在编译时获得F#中的DU.A类型?

typeof<DU> // compiles
typeof<DU.A> // error FS0039: The type 'A' is not defined
typeof<A> // error FS0039: The type 'A' is not defined

我可以很容易地在F#中注册一个用于反序列化的函数 .

open System
open ServiceStack.Text

JsConfig<DU>.RawDeserializeFn <-
    Func<_, _>(fun s -> printfn "Hooked"; if s = "A" then A else B)

对于具体类型DU.A和DU.B,是否可以完全在F#中注册序列化函数?

3 回答

  • 8

    虽然所有的行为(抽象类等)不仅仅是一个实现细节,它实际上是由规范定义的,这些东西是不能从F#访问的 - 这是spec的引用

    已编译的联合类型U具有:·每个空联合情况C的一个CLI静态getter属性U.C.此属性获取表示每个此类情况的单个对象 . ·每个非空联合案例C的一个CLI嵌套类型U.C . 此类型对于union案例的每个字段都具有实例属性Item1,Item2 ....如果只有一个字段,则为单个实例属性Item . 但是,只有一个案例的编译联合类型没有嵌套类型 . 相反,union类型本身扮演案例类型的角色 . ·每个非空联合情况C的一个CLI静态方法U.NewC . 此方法为该情况构造一个对象 . ·每个案例C的一个CLI实例属性U.IsC . 此属性对于案例返回true或false . ·每个案例C的一个CLI实例属性U.Tag . 此属性获取或计算与案例对应的整数标记 . ·如果U有多个case,则它有一个CLI嵌套类型U.Tags . 对于每种情况,U.Tags都会输入一个整数文字,从零开始按递增顺序排列 . ·除了任何用户定义的属性或方法之外,编译的联合类型还具有实现其自动生成的接口所需的方法 . 这些方法和属性可能无法直接从F#中使用 . 但是,这些类型具有面向用户的List.Empty,List.Cons,Option.None和Option.Some属性和/或方法 .

    重要的是,“这些方法和属性可能不会从F#中使用” .

  • 5

    F#中的DU是单一类型的事实是其有用性的关键 . F#方法是使用模式匹配:

    JsConfig<DU>.SerializeFn <- function
      | A -> "A"
      | B -> "B"
    

    这应该有效,因为联合案例不仅是C#中的嵌套类型,也是子类型 . 当然,如果ServiceStack没有工作 .

  • 4

    Daniel是正确的,您可以通过为基本类型 DU 注册序列化函数来完成此操作 . 这是一个更全面的例子

    open System
    open ServiceStack.Text
    
    type DU = A | B
    
    let serialize = function
        | A -> "A"
        | B -> "B"
    
    let deserialize = function
        | "A" -> A
        | "B" -> B
        | _   -> failwith "Can't deserialize"
    
    JsConfig<DU>.SerializeFn <- Func<_,_>(serialize)
    JsConfig<DU>.DeSerializeFn <- Func<_,_>(deserialize)
    
    let value = [| A; B |]
    let text = JsonSerializer.SerializeToString(value)
    let newValue = JsonSerializer.DeserializeFromString<DU[]>(text)
    

    结果:

    val value : DU [] = [|A; B|]
    val text : string = "["A","B"]"
    val newValue : DU [] = [|A; B|]
    

相关问题