For my project in practice, I've been using the technique described in
Expert F#, Chapter 9, Using XML as a Concrete Language Format (starting p.212).
I have a feeling that by using reflection, it might be possible to automate the (de)serialization of discriminated union types into XML format just like it's possible to automate the (de)serialization of record types into an CSV format.
Anyone up for the challenge? :-)
Let me elaborate. For discriminated unions, perhaps some form of automatic XML format would make sense. The .NET serialization doesn't work out of the box, because discriminated unions don't have empty constructors.
...automatic XML ... The .NET serialization doesn't work out of the box, because discriminated unions don't have empty constructors.
Investigating the current status, the next step is to duplicate the problem namin encountered. Then to devise some appropriate solution. This first automated approach will likely generate an XML representation that is more verbose than the succinct one we did by hand.
Background info:
Xml Serializer is described here:
an example of C# disassembly of a discriminated union using Reflector is here:
Clearly, XmlSerialize of F# structures isn't getting us to the desired result. Possibly this can all be fixed by internal changes to F# compiler -- though the ignoring of the standard [NonSerialized] attribute by XmlSerializer is worrisome. XmlSerializer has its own attributes for controlling its behavior, but it shouldn't be necessary to use those for most .NET data.
EDIT: See "Using Reflection to Serialize F# Data to/from XML", [link:cs.hubfs.net] for the implementation of a generalized solution.
Translated Micado serialization from C#, and used that to xml-serialize an int, and then [unsuccessfully!] a discriminated union containing ints:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
type NodeIndex = int type Wires = Complete | Input of NodeIndex // Input Terminal with wire coming out. | Output of NodeIndex // Output terminal with wire coming in. | Thru of NodeIndex * NodeIndex module IO = System.IO module TEXT = System.Text module X = System.Xml module XS = System.Xml.Serialization let UTF8ByteArrayToString (chars:byte[]) :string = let encoding = new TEXT.UTF8Encoding() encoding.GetString(chars) /// return Xml string. let SerializeObject (ob:obj) :string = let typ = ob.GetType() let mem = new IO.MemoryStream() let xs = new XS.XmlSerializer( typ ) let writer = new X.XmlTextWriter(mem, TEXT.Encoding.UTF8) xs.Serialize(writer, ob) let mem2 = writer.BaseStream :?> IO.MemoryStream let resultStr = UTF8ByteArrayToString (mem2.ToArray()) resultStr // --- interactive session --- pam (SerializeObject (box(12))) "Serial 12" //> "<?xml version=\"1.0\" encoding=\"utf-8\"?><int>12</int>" = Serial 12 let w1 = Input 1 pam w1 "w1" //> Input 1 = w1 //SerializeObject (box(w1)) //==> *** ERROR -- No Parameterless Constructor
The integer came through as "<int>12</int>", but the union threw an error. Disassemblying in Reflector, we see that each alternate (here, "Input") of the union becomes a nested class, with a constructor that takes the needed data -- here, "Wires._Input(_Input1:int)"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
[Serializable, CompilationMapping(SourceLevelConstruct.SumType)] public class Wires : IStructuralHash, IComparable { ... [Serializable] public class _Input : MyModule.Wires { // Fields public int _Input1; // Methods public _Input(int _Input1) { this._Input1 = _Input1; } } ... }
This seems to be a bug in F#'s implementation of unions. For the sake of serialization, there should be a private parameterless constructor added to each alternative:
1 2 3 4
private _Input(){}
Further experimentation shows additional issues serializing F# types.
Record structure:
1 2
type WRecord = { In: NodeIndex; Out: NodeIndex }
Also lacks a private parameterless constructor for the serializer to use.
Class with fields:
1 2 3 4 5 6 7 8
type WClass() = [<DefaultValue>] val mutable In: NodeIndex [<DefaultValue>] val mutable Out: NodeIndex with member w.init (in0:NodeIndex) (out0:NodeIndex) = w.In <- in0; w.Out <- out0;
That is the ugly construct I came up with to be able to serialize. Has an empty constructor, and then an init member that client must call to fill the mutable fields. (NOTE: if the implementation added a private parameterless constructor, this work-around would not be needed.) Even then, it yielded a verbose serialization:
<WClass><_In>11</_In><_Out>22</_Out><In>11</In><Out>22</Out></WClass>
The ideal output would be:
<WClass><In>11</In><Out>22</Out></WClass>
What happened is that F# implements as an internal field "_In" combined with a property "In", and both were given values in the serialization. The fix would be for F# to mark the internal field's as "NonSerialized". See "Object Serialization in the .NET Framework/ Selective Serialization" [link:msdn2.microsoft.com] Here, I will do so manually:
1 2 3 4 5 6 7 8
type WClass() = [<DefaultValue>][<System.NonSerialized>] val mutable In: NodeIndex [<DefaultValue>][<System.NonSerialized>] val mutable Out: NodeIndex with member w.init (in0:NodeIndex) (out0:NodeIndex) = w.In <- in0; w.Out <- out0;
Which unfortunately doesn't change the XmlSerialized result. Examining Disassembly in Reflector, the fields are now marked "[NonSerialized, DefaultValue, NonSerialized]". Not sure why assembly space is being wasted by the double-marking of NonSerialized. Don't know why XmlSerializer is ignoring the normal Serialization markings.
As a separate issue, putting such a serialization into a file wouldn't yield human readable text, as no newlines or indentation is added.
Added the following logic to convert the results of XmlSerialize into a human readable file. The approach is to let XmlDocument do the pretty-printing work, via LoadXML and Save:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
module RE = System.Text.RegularExpressions /// Strip the xml version line "<?...?>" /// NOTE: Also stripping invalid char that appeared BEFORE that version info! let stripXmlVersion (s:string) :string = //let re = new RE.Regex(@"<?.*?>") RE.Regex.Replace(s, @".*\<\?.*\?\>", "") /// Convert from all-in-one-line string designed for PC interchange, /// To a human readable file with newlines and indentation. /// NOTE: XmlDocument can't handle the (standard!) xml version info /// at the string start, so strip it out first. let SavePrettyXml (s:string) (filename:string) :unit = let doc = new X.XmlDocument() let s2 = stripXmlVersion s doc.LoadXml (stripXmlVersion s) doc.Save filename /// XmlSerialize object and save to specified file. let ser2file (ob:#obj) (filename:string) = let xmlString = SerializeObject (box(ob)) SavePrettyXml xmlString filename ser2file wc "wclass.xml"
--- file "wclass.xml" contents: ---
1 2 3 4 5 6
<WClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <_In>11</_In> <_Out>22</_Out> <In>11</In> <Out>22</Out> </WClass>
NOTE: "scheme" => "schema"
How about a three-way interchange between a compact form that is easy to type, an XML representation, and F# data structures?
Sounds like a straightforward test of the parser generator I am constructing. Good fit to FParsec abilities, so this gives me further motivation to construct my generator on FParsec.
Even before the generator exists, manually constructing [F# code calling FParsec functions] a parser for a specific schema should be simple enough; I will give that a go. If you want to try that yourself, see [link:quanttec.com]
Can you provide a short example of one such recursive data structure involving discriminated unions, so that I know I am heading on the track you had in mind? ~TMSteve
The Expert F# example mentioned above (which is about Composite Scenes) is a good simple example.
In my case, here is an example of a discriminating union I am actually using:
1 2 3 4 5 6
type FlowBox = Primitive of Attachments * Used | Extended of Attachments * Used * FlowBox | Or of Attachments * FlowBox array * Ordering | And of Attachments * FlowBox array | Seq of Attachments * FlowBox array
In the same style as the Expert F# example, I parse an XML representation of this type as follow:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
let rec extractBox (node : XmlNode) = let attribs = node.Attributes let childNodes = node.ChildNodes let attachments = extractAttachments(attribs) let childBoxes() = [| for child in childNodes -> extractBox(child) |] match node.Name with | "Primitive" -> FlowBox.Primitive(attachments, extractUsed(attribs)) | "Extended" -> FlowBox.Extended(attachments, extractUsed(attribs), extractBox (childNodes.Item(0))) | "Or" -> FlowBox.Or(attachments, childBoxes(), extractOrdering(attribs)) | "And" -> FlowBox.And(attachments, childBoxes()) | "Seq" -> FlowBox.Seq(attachments, childBoxes()) | s -> failwith ("unrecognized box type " ^ s)
I am omitting lots of code here :-) If you're interested, the export and import to XML is done in the module Serialization of the following file:
[link:code.google.com]
Working towards a schema-driven reader/writer for F# discriminated unions.
The first step is to take a test case and write by hand the code to read and write a FlowBox. This version is NOT driven by a schema. It just shows what needs to occur. This code will be similar to what namin already did, in the file he linked. I've stripped out anything not needed for this example, and reorganized:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
#light type NodeIndex = int type Wires = Complete | Input of NodeIndex // Input Terminal with wire coming out. | Output of NodeIndex // Output terminal with wire coming in. | Thru of NodeIndex * NodeIndex with static member create inputWire outputWire = match inputWire, outputWire with | None, None -> Complete | None, Some output -> Input output // careful not to reverse | Some input, None -> Output input | Some input, Some output -> Thru (input, output) member w.inputOpt = match w with | Complete | Input _ -> None | Output inIndex | Thru (inIndex, _ ) -> Some inIndex member w.outputOpt = match w with | Complete | Output _ -> None | Input outIndex | Thru (_, outIndex ) -> Some outIndex type FlowBox = Prim of Wires // Primitive | Extd of Wires * FlowBox // Extended | And of Wires * FlowBox array /// The XML Serialization is loosely inspired by Expert F#, Chapter 9, /// section Using XML As a Concrete Language Format (starting p.212) module Serialization = open System.Xml let InputStr = "input"; let OutputStr = "output"; let PrimStr = "Primitive"; let ExtdStr = "Extended"; let AndStr = "And"; // ----- Build data from XML. ----- let importInts (text : string) = text.Split([|'[';']';';'|]) |> Array.map (fun s -> s.Trim()) |> Array.filter (fun s -> s <> "") |> Array.map System.Int32.Parse let importIntSet = importInts >> Set.of_array let extractIntOption attrName (attribs : XmlAttributeCollection) = let item = attribs.GetNamedItem(attrName) if item = null then None else Some (Int32.of_string(item.Value)) let extractWires (attribs : XmlAttributeCollection) = let inputOpt = extractIntOption InputStr attribs let outputOpt = extractIntOption OutputStr attribs Wires.create inputOpt outputOpt let rec extractBox (node : XmlNode) = let attribs = node.Attributes let childNodes = node.ChildNodes let wires = extractWires(attribs) let childBoxes() = [| for child in childNodes -> extractBox(child) |] match node.Name with | "Primitive" -> FlowBox.Prim(wires) | "Extended" -> FlowBox.Extd(wires, extractBox (childNodes.Item(0))) | "And" -> FlowBox.And(wires, childBoxes()) | s -> failwith ("unrecognized box type " ^ s) let extractFlowBoxDoc (doc:XmlDocument) :FlowBox = //ALTERNATE let rootNode = doc.DocumentElement; let rootNode = doc.FirstChild; if rootNode = null then failwith "empty doc" extractBox rootNode // ----- Build XML tree from data. ----- let rec box2XML (doc: XmlDocument) (fb: FlowBox ) :XmlElement = let mutable name = "" let wo = match fb with | Prim w -> name <- PrimStr; w | Extd (w, fb) -> name <- ExtdStr; w | And (w, fba) -> name <- AndStr; w let node = doc.CreateElement(name) let sOf (i:NodeIndex) = i.ToString() let setAttrib name w = node.SetAttribute(name, sOf w) match wo.inputOpt with Some w -> (setAttrib InputStr w) | _ -> () match wo.outputOpt with Some w -> (setAttrib OutputStr w) | _ -> () let appendFb fb = node.AppendChild( (box2XML doc fb) ) |> ignore match fb with | Prim w -> () | Extd (w, fb) -> appendFb fb | And (w, fba) -> Array.iter appendFb fba node let buildFlowBoxDoc (fb: FlowBox) :XmlDocument = let doc = new XmlDocument() doc.AppendChild (box2XML doc fb) |> ignore doc // ---------- Tests ---------- open System.Xml open Serialization // The module above. let ps s = s |> printfn "%A" let psm s msg = printfn "%A = %s" s msg let C = Complete let I w = Input w let O w = Output w let T w1 w2 = Thru (w1, w2) let P w = Prim w let E w fb = Extd (w, fb) let A w fba = And (w, fba) let w1 = I 1 let w2 = T 1 2 let w3 = O 2 let fb1 = P w1 let fb2 = E w2 fb1 // Not a very meaningful diagram... let fb3 = A w3 [| fb1; fb2 |] psm w1 "w1" psm w2 "w2" psm w3 "w3" psm fb1 "fb1" psm fb2 "fb2" psm fb3 "fb3" // Create XML for flowbox. let doc = buildFlowBoxDoc fb3 ps doc.OuterXml // TODO: Missing "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" doc.Save("flowbox.xml") // Save as file. // Rebuild flowbox from XML. let fbIn = extractFlowBoxDoc doc psm fbIn "fbIn" // Verify round trip. psm (fbIn = fb3) "(fbIn = fb3)"
== output ==>
1 2 3 4 5 6 7 8 9
Input 1 = w1 Thru (1,2) = w2 Output 2 = w3 Prim Input 1 = fb1 Extd (Thru (1,2),Prim Input 1) = fb2 And (Output 2,[|Prim Input 1; Extd (Thru (1,2),Prim Input 1)|]) = fb3 "<And input=\"2\"><Extended input=\"1\" output=\"2\"></Extended></And>" And (Output 2,[|Prim Input 1; Extd (Thru (1,2),Prim Input 1)|]) = fbIn true = (fbIn = fb3)
Here is the generated file, "flowbox.xml" (TODO: Start with standard "<?xml version=\"1.0\" encoding=\"utf-8\" ?>") :
1 2 3 4
<And input="2"> <Extended input="1" output="2"> </Extended> </And>
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
Hi,
I really like the example in the Language-Oriented Chapter of Expert F# starting on p. 245 where reflection is used to automatically convert a CSV file into a sequence of records. It's quite magical indeed.
I am wondering if anyone has thought of extending this technique for more fancy types, notably discriminated unions that might be recursive. I guess this would require some parser which uses reflection.
Any pointers or ideas would be appreciated. Thanks.