如何将字符串解析为任何F#数据?

如何将字符串解析为任何F#数据?,f#,f#-data,F#,F# Data,在F#中,任何数据都可以通过函数sprintf进行字符串化,如下所示: type someKindOfDataType = ... let data : someKindOfDataType = ... sprintf "%A" data 我们是否可以使用反转函数将字符串解析回某种类型的数据类型,如下所示: let parse<'someKingOfDataType> (s:string) : someKindOfDataType = .... let parse您描述的是通常称

在F#中,任何
数据
都可以通过函数
sprintf
进行字符串化,如下所示:

type someKindOfDataType = ...
let data : someKindOfDataType = ...
sprintf "%A" data
我们是否可以使用反转函数将字符串解析回某种类型的数据类型,如下所示:

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

let parse您描述的是通常称为序列化的内容——从内存中的数据结构转换为可通过网络传输的表示,可以是XML、JSON、二进制等,反序列化——反之亦然

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

如果您想将F#数据序列化为字符串,我建议您通过库(如)使用JSON

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

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|]
let a = Int32.Parse "5"
let b = 
    match Int32.TryParse "5" with
    | true, value -> Some value
    | _           -> None
Newtonsoft.Json.JsonConvert.SerializeObject[|约3;无|]
//“[{”大小写“:“某些”,“字段“:[3]},null]””
Newtonsoft.Json.JsonConvert.DeserializeObject“”“[{”大小写“:“一些”,“字段“:[3]},null]”
//[|大约3;没有]

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

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

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

如果您想将F#数据序列化为字符串,我建议您通过库(如)使用JSON

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

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|]
let a = Int32.Parse "5"
let b = 
    match Int32.TryParse "5" with
    | true, value -> Some value
    | _           -> None
Newtonsoft.Json.JsonConvert.SerializeObject[|约3;无|]
//“[{”大小写“:“某些”,“字段“:[3]},null]””
Newtonsoft.Json.JsonConvert.DeserializeObject“”“[{”大小写“:“一些”,“字段“:[3]},null]”
//[|大约3;没有]

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

标准.NET方法是,通常在您尝试解析的类型的类中使用
Parse
TryParse
方法

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

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|]
let a = Int32.Parse "5"
let b = 
    match Int32.TryParse "5" with
    | true, value -> Some value
    | _           -> None
如果您想使用一个库,它既有函数
parse
又有函数
tryParse
,这两个函数都可以为您执行上述所有操作:

#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

只要该类型定义了
Parse
TryParse
,它就可以工作。

标准的.NET方式是,通常在您试图解析的类型的类中使用
Parse
TryParse
方法

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

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|]
let a = Int32.Parse "5"
let b = 
    match Int32.TryParse "5" with
    | true, value -> Some value
    | _           -> None
如果您想使用一个库,它既有函数
parse
又有函数
tryParse
,这两个函数都可以为您执行上述所有操作:

#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

只要该类型定义了
Parse
TryParse
,它就可以工作。

非常感谢您的回答。很高兴学习你的图书馆和帖子。您在F#+中重载内联函数解析的技术非常有趣和出色。它允许使用返回类型作为签名来选择converter.fs的类型解析器中静态解析函数中实现的解析器。然而,正如您所提到的,每个类型都需要编写其唯一的解析器函数并在类型解析器中定义。这不是我想要的。但再次感谢您的回答。在类型
解析器中不一定如此,这仅适用于没有“内置”解析(或最终是TryParse)方法的类型。这里的例子已经有了。关于“如何将字符串解析为类型值并将类型值字符串化”的问题让我想到了Haskell,它的标准功能是允许任何用户定义的派生类型显示、读取、,因此,该类型将自动派生重载的“read”和“print”函数,其工作方式与stringify和parse类似!我爱哈斯克尔。是的,当我回答你的问题时,我也想到了这一点;)非常感谢你的回答。很高兴学习你的图书馆和帖子。您在F#+中重载内联函数解析的技术非常有趣和出色。它允许使用返回类型作为签名来选择converter.fs的类型解析器中静态解析函数中实现的解析器。然而,正如您所提到的,每个类型都需要编写其唯一的解析器函数并在类型解析器中定义。这不是我想要的。但再次感谢您的回答。在类型
解析器中不一定如此,这仅适用于没有“内置”解析(或最终是TryParse)方法的类型。这里的例子已经有了。关于“如何将字符串解析为类型值并将类型值字符串化”的问题让我想到了Haskell,它的标准功能是允许任何用户定义的派生类型显示、读取、,因此,该类型将自动派生重载的“read”和“print”函数,其工作方式与stringify和parse类似!我爱哈斯克尔。是的,当我回答时,我也想到了这一点