序列化F#函数



使用F#我有一些配置,我想使用Newtonsoft.Json将其序列化到磁盘。配置数据是一种记录类型。记录类型中的一个字段是字符串->bool类型的函数,用于将字符串与给定值进行比较。例如

(fun (x:string) -> x = "1")

序列化类型成功,但字段未成功存储(记录为"{}"(,因此反序列化失败。这似乎是故意的。

如何存储函数,使其在反序列化时可以用于从磁盘填充记录类型,并且仍然是可执行的?

我曾将引号视为一种将表达式存储为数据的方法,但我不确定这是否是可行的。如果是的话,那么我正在努力让它发挥作用。

如何实现我的需求?

更新

type Logic = string -> bool

存储配置的记录类型;

type Exclusion = 
| FromDataValue of QItem * Logic * ExcludedItems
| FromDataValuesAnd of (QItem * Logic) seq * ExcludedItems          
| FromDataValuesOr of (QItem * Logic) seq seq * ExcludedItems 

Exclusion记录由用户填充,并针对某些数据集运行,这些数据集不包括返回集合中的项目。QItem表示数据集中应用Logic函数的字符串,如果返回true,则ExcludedItems中的项将从结果中排除。

最初,配置是由用户在解决方案中创建的,所以一切都很好。然而,一旦创建了配置,我希望能够将配置保存到光盘中,以便在需要时加载并再次运行。

所以我需要能够存储它,但我希望能够将它存储为字符串,然后在加载时再次运行它。

您可以将函数序列化为JSON,然后对其进行反序列化,然后使用FSPickler:执行该函数

open MBrace.FsPickler
open MBrace.FsPickler.Json
open System.IO
open System.Text
let serializer = JsonSerializer(indent = true)
let utf8 = UTF8Encoding(false)
let toJson (x: 'a) =
use stream = new MemoryStream()
serializer.Serialize(stream, x)
stream.ToArray() |> utf8.GetString
let parseJson<'a> json =
use reader = new StringReader(json)
serializer.Deserialize<'a>(reader)
let f = fun x -> x + 1
let serialized = toJson f
let deserialized = parseJson<int -> int> serialized
deserialized 1 // returns 2

函数的序列化JSON如下所示:

{
"FsPickler": "4.0.0",
"type": "Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32]",
"value": {
"_flags": "subtype",
"subtype": {
"Case": "NamedType",
"Name": "FSI_0002+serialized@23",
"Assembly": {
"Name": "FSI-ASSEMBLY",
"Version": "0.0.0.0",
"Culture": "neutral",
"PublicKeyToken": ""
}
},
"instance": {}
}
}

虽然instance为空,但它记录了为函数创建的匿名类型的元数据。这样,只要函数类型在执行反序列化的AppDomain中可用,它就可以在调用反序列化版本时调用正确的代码。

编辑

如果您想串行化函数的逻辑,可以使用FSPickler来串行化代码引用:

open MBrace.FsPickler
open MBrace.FsPickler.Json
open FSharp.Quotations
open FSharp.Quotations.Evaluator
open System.IO
open System.Text
let serializer = JsonSerializer(indent = true)
let utf8 = UTF8Encoding(false)
let toJson (x: 'a) =
use stream = new MemoryStream()
serializer.Serialize(stream, x)
stream.ToArray() |> utf8.GetString
let parseJson<'a> json =
use reader = new StringReader(json)
serializer.Deserialize<'a>(reader)
let f = <@ fun x -> x + 1 @>
let serialized = toJson f
let deserialized = parseJson<Expr<int -> int>> serialized
let increment = deserialized |> QuotationEvaluator.Evaluate
increment 1

通过这种方式,引号被序列化为JSON,所有逻辑都被描述为表达式树,当你对它进行反序列化时,你可以使用FSharp.Quotations.Evaluator库将它变成一个可以调用的可运行函数。

JSON现在相当大,但可以在任何地方进行反序列化和评估:

{
"FsPickler": "4.0.0",
"type": "Microsoft.FSharp.Quotations.FSharpExpr`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32]]",
"value": {
"attribs": [
{
"attribs": [],
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "NewTupleOp",
"Item": {
"Case": "GenericTypeInstance",
"GenericDefinition": {
"Case": "NamedType",
"Name": "System.Tuple`2",
"Assembly": {
"Name": "mscorlib",
"Version": "4.0.0.0",
"Culture": "neutral",
"PublicKeyToken": "b77a5c561934e089"
}
},
"TypeArgs": [
{
"Case": "NamedType",
"Name": "System.String",
"Assembly": {
"_flags": "cached",
"id": 9
}
},
{
"Case": "GenericTypeInstance",
"GenericDefinition": {
"Case": "NamedType",
"Name": "System.Tuple`5",
"Assembly": {
"_flags": "cached",
"id": 9
}
},
"TypeArgs": [
{
"_flags": "cached",
"id": 11
},
{
"Case": "NamedType",
"Name": "System.Int32",
"Assembly": {
"_flags": "cached",
"id": 9
}
},
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
}
]
}
]
}
},
"Item2": [
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 11
},
"instance": "DebugRange"
},
"Item2": {
"_flags": "cached",
"id": 11
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "NewTupleOp",
"Item": {
"_flags": "cached",
"id": 12
}
},
"Item2": [
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 11
},
"instance": "C:\Users\aeshbach\AppData\Local\Temp\~vs220A.fsx"
},
"Item2": {
"_flags": "cached",
"id": 11
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 32
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 11
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 32
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 25
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
}
]
}
}
]
}
}
],
"term": {
"Case": "LambdaTerm",
"Item1": {
"isMutable104": false,
"name": "x",
"stamp": 0,
"typ": {
"_flags": "cached",
"id": 15
}
},
"Item2": {
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "StaticMethodCallOp",
"Item": {
"Case": "GenericMethodInstance",
"GenericDefinition": {
"Case": "Method",
"Signature": "T3 op_Addition[T1,T2,T3](T1,T2)",
"IsStatic": true,
"DeclaringType": {
"Case": "NamedType",
"Name": "Microsoft.FSharp.Core.Operators",
"Assembly": {
"Name": "FSharp.Core",
"Version": "4.4.1.0",
"Culture": "neutral",
"PublicKeyToken": "b03f5f7f11d50a3a"
}
},
"ReflectedType": null
},
"TypeArgs": [
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
}
]
}
},
"Item2": [
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "VarTerm",
"Item": {
"_flags": "cached",
"id": 40
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 1
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
}
]
}
}
}
}
}

最新更新