Где я могу найти сериализатор для F # дискриминируемых союзов? - PullRequest
2 голосов
/ 15 сентября 2010

Мне нужно сохранить абстрактное синтаксическое дерево, представленное с использованием распознаваемых объединений F #, в удобочитаемом компактном формате, таком как формат, уже использованный в языке F # для создания распознаваемых объединений, который я могу позже прочитать в экземплярах различимых объединений.Я немного удивлен, что библиотека F # не поддерживает это, поскольку это, безусловно, должно быть сделано эффективным способом уже в компиляторе и F # интерактивно.

Существуют ли какие-либо реализации с открытым / открытым исходным кодом для этого?это разумным (но не обязательно чрезвычайно) эффективным способом?

Примечание: я не хочу сериализацию на основе XML.

1 Ответ

5 голосов
/ 15 сентября 2010

РЕДАКТИРОВАТЬ: Ни один из ответов ниже действительно не соответствует вашим критериям, но я публикую на случай, если другие, ищущие объединение сериализации, найдут их полезными.Я не знаю, каким-либо образом, каким-либо библиотечным способом пересмотреть вывод sprintf "%A" для объединения - имейте в виду, что перед компилятором и FSI стоит совсем другая задача, зная области видимости и имея дело с пространствами имен и квалифицированными именами и тенямичто угодно, и даже игнорируя это, анализ данных, переносимых объединениями (целые, строки, произвольные объекты и т. д.), потенциально сам по себе является целой задачей.

Вот одна из стратегий для сериализации объединения, как частьнебольшой пример программы.(KnownTypeAttribute может принимать имя метода, и вы можете использовать некоторые отражения для получения типов.) Это очень простой способ добавить крошечный кусочек кода в объединение для получения сериализации.

open Microsoft.FSharp.Reflection 
open System.Reflection 
open System.Runtime.Serialization 
open System.Xml

[<KnownType("KnownTypes")>]
type Union21WithKnownTypes = 
    | Case1 of int * int
    | Case2 of string
    static member KnownTypes() = 
        typeof<Union21WithKnownTypes>.GetNestedTypes(
            BindingFlags.Public 
            ||| BindingFlags.NonPublic) |> Array.filter FSharpType.IsUnion 

let dcs = new DataContractSerializer(typeof<Union21WithKnownTypes[]>)
let arr = [| Case1(1,1); Case2("2") |]
printfn "orig data: %A" arr
let sb = new System.Text.StringBuilder()
let xw = XmlWriter.Create(sb)
dcs.WriteObject(xw, arr)
xw.Close()
let s = sb.ToString()
printfn ""
printfn "encoded as: %s" s
printfn ""
let xr = XmlReader.Create(new System.IO.StringReader(s))
let o = dcs.ReadObject(xr)
printfn "final data: %A" o

Вот версия JSON:

open Microsoft.FSharp.Reflection  
open System.Reflection  
open System.Runtime.Serialization  
open System.Runtime.Serialization.Json  
open System.Xml 

[<KnownType("KnownTypes")>] 
type Union21WithKnownTypes =  
    | Case1 of int * int 
    | Case2 of string 
    static member KnownTypes() =  
        typeof<Union21WithKnownTypes>.GetNestedTypes( 
            BindingFlags.Public  
            ||| BindingFlags.NonPublic) |> Array.filter FSharpType.IsUnion  

let dcs = new DataContractJsonSerializer(typeof<Union21WithKnownTypes[]>) 
let arr = [| Case1(1,1); Case2("2") |] 
printfn "orig data: %A" arr 
let stream = new System.IO.MemoryStream()
dcs.WriteObject(stream, arr) 
stream.Seek(0L, System.IO.SeekOrigin.Begin) |> ignore
let bytes = Array.create (int stream.Length) 0uy
stream.Read(bytes, 0, int stream.Length) |> ignore
let s = System.Text.Encoding.ASCII.GetString(bytes)
printfn "" 
printfn "encoded as: %s" s 
printfn "" 
stream.Seek(0L, System.IO.SeekOrigin.Begin) |> ignore
let o = dcs.ReadObject(stream)
printfn "final data: %A" o 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...