【问题标题】:How to parse string to any F# data?如何将字符串解析为任何 F# 数据?
【发布时间】:2017-09-27 19:02:05
【问题描述】:

在 F# 中,任何data 都可以通过函数sprintf 成为stringify,如下所示:

type someKindOfDataType = ...
let data : someKindOfDataType = ...
sprintf "%A" data

我们能否有一个反转函数将字符串解析回someKindOfDataType,如下所示:?

let parse<'someKingOfDataType> (s:string) : someKindOfDataType = ....

就像 javascript 中的 JSON.parse 一样?

【问题讨论】:

    标签: f# f#-data


    【解决方案1】:

    您正在描述通常称为 序列化 - 从内存中的数据结构转换为可以通过网络传输的表示形式,可以是 XML、JSON、二进制等。 - 和 反序列化 - 反过来。

    sprintf "%A" 旨在提供方便的数据可视化表示,通常仅用于开发目的,而不是用于生产。它实际上并没有进行序列化,因为没有办法反序列化。

    如果您想将 F# 数据序列化为字符串,我建议通过 Newtonsoft.Json 等库使用 JSON。

    请注意,这不会产生类似于 F# 源代码的字符串,例如 sprintf "%A",因为目的不同。一个例子:

    Newtonsoft.Json.JsonConvert.SerializeObject [|Some 3; None|]
    // """[{"Case":"Some","Fields":[3]},null]"""
    
    Newtonsoft.Json.JsonConvert.DeserializeObject<int option []> """[{"Case":"Some","Fields":[3]},null]"""
    // [|Some 3; None|]
    

    您需要提供要反序列化的类型,如果字符串不代表该类型的有效实例,此操作可能会引发异常。

    【讨论】:

    • 非常感谢您的回答。你的简单例子让我知道你的答案就是我想要的。
    【解决方案2】:

    标准的 .NET 方式是,通常您将在您尝试解析的类型的类中使用 ParseTryParse 方法。

    但在 F# 中,TryParse 函数不是很友好,因为它使用输出参数,但 F# 编译器仍然允许您将其视为元组,这会使事情变得更好,但您仍然希望获得一个选项,这里是一个例子:

    let a = Int32.Parse "5"
    let b = 
        match Int32.TryParse "5" with
        | true, value -> Some value
        | _           -> None
    

    如果您想使用库 F#+ 具有 parsetryParse 两个函数,它们可以为您完成上述所有操作:

    #r @"FSharpPlus.dll"
    open FSharpPlus
    open System
    
    let (a:int) = parse "5"
    let (b:int option) = tryParse "5"
    let (c: Net.IPAddress option) = tryParse "10.0.0.1"
    
    // val a : int = 5
    // val b : int option = Some 5
    // val c : Net.IPAddress option = Some 10.0.0.1
    

    只要类型定义了ParseTryParse,它就可以工作。

    【讨论】:

    • 非常感谢您的回答。很高兴学习您的图书馆和帖子。您在 F#+ 中重载内联函数解析的技术既有趣又出色。它允许使用返回类型作为签名来选择在converter.fs 的类型Parser 中的静态解析函数中实现的解析器。但是,正如您提到的每种类型都写了它唯一的解析器函数并在类型解析器中定义。这不是我的。但再次感谢您的回答。
    • 不一定在Parser 类型中,仅适用于没有“内置” Parse(或最终 TryParse)方法的类型。这里的例子已经有了。
    • 这个“如何将字符串解析为类型的值并将类型的值字符串化”的问题将我引向 Haskell,它具有允许任何用户定义的类型派生显示的标准功能,阅读,因此该类型将自动派生重载的 'read' 和 'print' 函数,它们的工作方式与 stringify 和 parse 一样!我喜欢 Haskell。
    • 是的,当我回答你的问题时,我也想到了同样的问题;)
    猜你喜欢
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 2018-05-17
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    相关资源
    最近更新 更多