序列化F#函数

时间:2018-07-26 13:27:42

标签: f# functional-programming json.net

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

<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>

<script>
    var socket = io.connect('http://localhost:4200');

    function sendMsg(){
        alert("OK");
        socket.emit('sendmsg', document.getElementById("text").value);
    }
</script>
<h2>Awesome Chat by Simon</h2>
<br>
    <input type="text" id="text">
    <input type="button" onclick="sendMsg()" value="Senden">

成功序列化类型,但是未成功存储字段(将其记录为“ {}”),因此反序列化失败。这似乎是设计使然。

如何存储一个函数,以便在反序列化后仍可将其用于从磁盘填充记录类型?

我已经将引号视为将表达式存储为数据的一种方式,但是我不确定这是否可行。如果是这样的话,我就在努力工作。

如何实现我所需要的?

更新;

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

记录类型存储配置;

type Logic = string -> bool

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

最初,配置是由用户在解决方案中创建的,因此一切正常。但是,一旦创建了配置,我希望能够将配置保存到光盘上,以便可以将其加载并在需要时再次运行。

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

1 个答案:

答案 0 :(得分:3)

您可以将函数序列化为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库将其转换为可调用的可运行函数。 / p>

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
                }
              }
            }
          ]
        }
      }
    }
  }
}