Compartir a través de


The JSON Parser Monad - Parsing JSON the fun way (Part 3)

It is finally time to tackle the problem that got us into looking at parsing data structures: a JSON blob in a late night. We started with a simple Parser definition, built very simple parsers, worked our away into building more complex ones by binding them together, and finally wrapped them into Parser Monads to leverage a simpler syntax through F#’s Computation Expressions.

We ended Part 2 with a set of general purpose parsers that we will use here to, finally, build the JSON parser.

Make sure to read Part 1 and Part 2 for a refresher if you need it.

First things first

We all know how JSON looks like, but for this exercise point your browser to json.org, and check the details of the structures it is built of. Let’s focus on the EBNF-like grammar on the right of the page: the values that form the JSON structured are strings, numbers, objects, arrays, booleans and null – it is pretty simple to represent that in F# using an algebraic type:

 type JSValue = 
    | JSString of string
    | JSNumber of float
    | JSObject of (JSValue * JSValue) list
    | JSArray of JSValue list
    | JSBool of bool
    | JSNull
F# Web Snippets

 

This will be our JSON abstract syntax tree and our parser will “fill up” this structure as it parsers the input string.

There is this simple trick I often use when I’m prototyping with some code, I don’t know yet how to implement some of the functionality of I need, but I want to rely on F#’s type system to make sure I’m on the right way. The idea is use Unchecked.defaultof to generate a default value for the return of your function while you don’t have an implementation for it (I guess this is just like the NotImplementedException VS throws in when generating class member stubs for you, just that we not throwing any exception in this case... we could, but we are not...). I always keep an undefined function handy, like this:

 let undefined<'a> = Unchecked.defaultof<'a>

 

For example, let’s write the functions of our JSON parser based on the grammar from json.org. The parsers for JSString, JSNumber, JSBool and JSNull are straight forward, they are just JSValue Parsers:

 let jsString = undefined<JSValue Parser>
let jsNumber = undefined<JSValue Parser>
let jsBool  = undefined<JSValue Parser>
let jsNull = undefined<JSValue Parser>

 

Note that that JSObject and JSArray both depend on JSValue, and JSValue on them, so these guys will need to be recursive:

 let rec jsValue = jsString <|> jsNumber <|> jsArray <|> jsBool <|> jsNull <|> jsObject
and jsElements = undefined<JSValue list Parser>
and jsArray = undefined<JSValue Parser>

and jsMembers = undefined<(JSValue * JSValue) list Parser>
and jsPair = undefined<(JSValue * JSValue) Parser>

and jsObject = undefined<JSValue Parser>

 

Finally we define the overall JSValue parser as a combination of parsers using the “or” parser combinator ( <|> ) form last post, meaning a JSValue parser is a jsString parser, or a jsNumber parser, or a jsArray parser, …, and so on.

I really like how this representation and types mimic the JSON grammar, for example: a JSON object is a value ( <JSValue Parser>) , composed of members ( <(JSValue * JSValue) list Parser>) of pairs of string : values ( <(JSValue * JSValue) Parser> ).

You can actually send the code above to F# Interactive and it will “run” just fine, showing that so far we've got the types correct:

val jsString : JSValue Parser = null
val jsNumber : JSValue Parser = null
val jsBool : JSValue Parser = null
val jsNull : JSValue Parser = null
val jsObject : JSValue Parser = null
val jsMembers : (JSValue * JSValue) list Parser = null
val jsPair : (JSValue * JSValue) Parser = null
val jsArray : JSValue Parser = null
val jsElements : JSValue list Parser = null
val jsValue : JSValue Parser = Parser <fun:op_LessBarGreater@32>

A parser at a time

Dividing to conquer… Let’s build a parser a time, substituting the default values by real implementations.

jsNull Parser

jsNull seems pretty simple to implement, whenever we see a null, we need to return JSNull. We can simply use the symb parser for that:

 let jsNull =
    let nullLiteral = s2cs "null"
    parser { let! _ = symb nullLiteral in return JSNull}

 

Remember, symb takes a char list as input and returns a parser that is able to parse that string. In this case we don’t really need the result of parsing “null”, we only need that it succeeds… and if it succeeds, we return JSNull . Let’s run it on Interactive:

> s2cs "null" |> apply jsNull;;
val it : (JSValue * char list) list = [(JSNull, [])]

jsBool Parser

jsBool is very similar to jsNull, however in this case we can return either JSBool(true)  or JSBool(false) : a perfect case for our “or” parser:

 let jsBool = 
    let trueLit = "true" |> s2cs
    let falseLit = "false" |> s2cs
    parser { let! _ = symb trueLit in return JSBool(true) } 
    <|> parser { let! _ = symb falseLit in return JSBool(false) }

 

Simple, right? jsBool is a parser that sequences two other parsers, one that parses “true” and the other that parses “false”; its return will depend on the parser that succeeds:

> s2cs "true" |> apply jsBool;;
val it : (JSValue * char list) list = [(JSBool true, [])]
> s2cs "false" |> apply jsBool;;
val it : (JSValue * char list) list = [(JSBool false, [])]

> s2cs "false true false true" |> apply (many jsBool);;
val it : (JSValue list * char list) list =
  [([JSBool false; JSBool true; JSBool false; JSBool true], [])]

jsNumber Parser

jsNumber is a bit more complex, check out the number grammar on json.org… We could use the same approach as before to slowly build it:

 let jsNumber = 
    let digitsParser = undefined<char list Parser>
    let intParser = undefined<char list Parser>
    let fracParser = undefined<char list Parser>
    let expParser = undefined<char list Parser>
    undefined<JSValue Parser>

 

digitsParser has to parse one to many digits; if you remember last post, we can accomplish it with the sat and many1 parsers, like this:

 let jsNumber = 
    let digitsParser = many1 (sat System.Char.IsDigit)
    let intParser = (zeroOrOne (text ['-'])) <@> digitsParser
    let fracParser = text ['.'] <@> digitsParser
    let expParser = 
        (text ['e'] <|> text ['E']) <@> 
        (zeroOrOne (text ['+'] <|> text ['-'])) <@>
        digitsParser
    parser {
        let! result = intParser <@> zeroOrOne fracParser <@> zeroOrOne expParser 
        let! _ = space
        return (result |> cs2s |> System.Double.Parse |> JSNumber)
    }     

 

intParser is quite interesting… it has to sequence zero or one applications of a ‘-‘ parser with the digitsParser. We don’t have a “one or zero” combinator in our bag of parsers from last post, and it seems a good candidate to be added to the list, so let’s define it:

 let zeroOrOne p = parser { let! ret = p in return ret } <|> parser { return [] }

 

When applied, this parser will try to parse the input string using parser p, and if that fails it returns an empty list Parser. Hover over the definition, this is an ‘a list Parser, so p also has to be an ‘a list Parser too, like the text parser defined in the last post:

> [ '-' ] |> apply (zeroOrOne (text ['-']));;
val it : (char list * char list) list = [(['-'], [])]

Let’s then build intParser using it:

 let intParser = (zeroOrOne (text ['-'])) <@> digitsParser

 

We are basically “appending” two parsers here: zeroOrOne (text ['-']) and digitsParser, this can also be quite common, so let’s build a parser combinator for that:

 let (<@>) p q = parser {
    let! rp = p
    let! rq= q
    return (rp @ rq)
}

 

Now intParser, fracParser and expParser can all be written using that:

 let intParser = (zeroOrOne (text ['-'])) <@> digitsParser
    let fracParser = text ['.'] <@> digitsParser
    let expParser = 
        (text ['e'] <|> text ['E']) <@> 
        (zeroOrOne (text ['+'] <|> text ['-'])) <@>
        digitsParser

 

All we need to do now is sequence all these parsers, one by one, concatenate the results and return the equivalent JSNumber:

 let jsNumber = 
    let digitsParser = many1 (sat System.Char.IsDigit)
    let intParser = (zeroOrOne (text ['-'])) <@> digitsParser
    let fracParser = text ['.'] <@> digitsParser
    let expParser = 
        (text ['e'] <|> text ['E']) <@> 
        (zeroOrOne (text ['+'] <|> text ['-'])) <@>
        digitsParser
    parser {
        let! result = intParser <@> zeroOrOne fracParser <@> zeroOrOne expParser 
        let! _ = space
        return (result |> cs2s |> System.Double.Parse |> JSNumber)
    }

 

Two comments here: because we are not using any of the combinators that take care of cleaning up spaces, we need to make sure to sequence a space parser in there. Second, all these parsers are char list parsers, so we can append them together in the end to come up with a string representation of the float number. Here it is in Interactive:

> "-1234.5678e-8" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber -1.2345678e-05, [])]
> "-1234.5678e8" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber -1.2345678e+11, [])]
> "-1234.5678e+8" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber -1.2345678e+11, [])]
> "-1234.5678E+8" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber -1.2345678e+11, [])]
> "1234.5678E+8" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber 1.2345678e+11, [])]
> "1234E+8" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber 1.234e+11, [])]
> "1234E-8" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber 1.234e-05, [])]
> "1234.5678" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber 1234.5678, [])]
> "1234" |> s2cs |> apply jsNumber;;
val it : (JSValue * char list) list = [(JSNumber 1234.0, [])]

How cool is that?!

jsString Parser

jsString is bit complex due to all the different  “production rules”. Let’s start by building a couple predicates based on those rules, and a helper function – this is straight out of JSON’s grammar:

 let isChar c = (c <> '\"') && (c <> '\\')
    let isEscChar = 
        let cs = "\"\\/bfnrt" |> List.ofSeq |> Set.ofList
        cs.Contains
    let replaceEscChar = function 'b' -> '\b' | 'f' -> '\f' | 'n' -> '\n'
                                | 'r' -> '\r' | 't' -> '\t' | other -> other

 

replaceEscChar will replace a JSON escape character, identified by isEscChar, by its backslash representation. Let’s build the escChar Parser with these guys’ help:

 let escChars = parser {
        let! _ = tChar '\\'
        let! c = sat isEscChar
        return (replaceEscChar c)
    }

 

We will also need a unicode parser, which will need to parse 4 hexadecimals, how about starting by putting together a hexDigit Parser?

 let isHexDigit = 
    let ds = ['A'..'F'] @ ['a'..'f'] @ ['0'..'9'] |> Set.ofList
    ds.Contains
let hexDigit = sat isHexDigit

 

Nothing new here… based on that, uniChars becomes:

 let uniChars = parser {
        let! _ = text [ '\\'; 'u' ]
        let! d1 = hexDigit
        let! d2 = hexDigit
        let! d3 = hexDigit
        let! d4 = hexDigit
        let r = 
            let s = new String [|d1; d2; d3; d4|]
            Byte.Parse(s, Globalization.NumberStyles.HexNumber)
            |> char
        return r
    }

 

There is one more pattern that will repeat on this and next parsers, for example, a JSON string is any char between ‘ “ ‘, objects are members between “{ }”, arrays are values between “[ ]”… It seems a good idea to build a “between chars” parser, no? Here it goes:

 let charToken = tChar >> token

let betweenChars c1 c2 f = parser {
    let! _ = charToken c1
    let! r = f()
    let! _ = charToken c2
    return r
}

 

betweenChars takes 2 chars and a function (that returns a parser), it binds then together using the let! syntax, and returns the result of applying the parser returned by the function f. And by the way, it comes with a freebie! The charToken Parser: it cleans up spaces after sequencing the tChar Parser. jsString is then defined as:

 let jsString = 
    let isChar c = (c <> '\"') && (c <> '\\')
    let isEscChar = 
        let cs = "\"\\/bfnrt" |> List.ofSeq |> Set.ofList
        cs.Contains
    let replaceEscChar = function 'b' -> '\b' | 'f' -> '\f' | 'n' -> '\n'
                                | 'r' -> '\r' | 't' -> '\t' | other -> other
    let escChars = parser {
        let! _ = tChar '\\'
        let! c = sat isEscChar
        return (replaceEscChar c)
    }
    let uniChars = parser {
        let! _ = text [ '\\'; 'u' ]
        let! d1 = hexDigit
        let! d2 = hexDigit
        let! d3 = hexDigit
        let! d4 = hexDigit
        let r = 
            let s = new String [|d1; d2; d3; d4|]
            Byte.Parse(s, Globalization.NumberStyles.HexNumber)
            |> char
        return r
    }
    let chars = many ((sat isChar) <|> escChars <|> uniChars)
    parser {
        let! cs = betweenChars '\"' '\"' (fun () -> chars)
        return (cs |> cs2s |> JSString)
    }

 

This is probably the biggest parser we have ever built!!! The chars Parser is a combination of a parser that parsers any JSON character (sat isChar), or an escChar or a uniChars. We sequence it using our new betweenChars parser combinator and return a JString of the parsed string. Kind of cool...

The recursive parsers

We already know that the jsValue parser is a combination of all the individual value parsers:

 let rec jsValue = jsString <|> jsNumber <|> jsArray <|> jsBool <|> jsNull <|> jsObject

 

Let’s build the array parser first. Per the JSON grammar, an array is a list of elements between “[ ]”, and elements are JSValues separated by ‘,’. This definition can be easily translated into:

 and jsElements = sepby jsValue (charToken ',')
and jsArray = parser {
    let! values = betweenChars '[' ']' (fun () -> jsElements)
    return (JSArray values)
    }

 

Here we are using the sepby parser combinator we learned last time to build the parser for the array elements. We then put it between ‘[‘ ‘]’ with betweenChars. It ends up being quite clean.

How about the objects? Objects are members between “{ }”, and members are pairs separated by “,”, which are in the format JString : JSValue. This definition also translates easily into F# with our parser combinators:

 and jsMembers = sepby jsPair (charToken ',')
and jsPair = parser {
    let! key = jsString
    let! _ = charToken ':'
    let! value = jsValue
    return (key, value)
    }
and jsObject = parser {
    let! members = betweenChars '{' '}' (fun () -> jsMembers)
    return (JSObject members)
    }

 

One last thing, let’s define a function to easily parse a json string; let’s require that any JSON string to be a JSObject, and use runParser with the jsObject to kick off the parsing sequence: given a string, return the JSON AST (which is a JSValue):

 let parseJson : (string -> JSValue) = runParser jsObject

 

The moment of truth

This is the moment we have been waiting so long for… does all this craziness really work? Go fetch some JSON data and let’s try it out, I’m grabbing some from https://json.org/example:

{"widget": {
    "debug": "on",
    "window": {
        "title": "Sample Konfabulator Widget",
        "name": "main_window",
        "width": 500,
        "height": 500
    },
    "image": {
        "src": "Images/Sun.png",
        "name": "sun1",
        "hOffset": 250,
        "vOffset": 250,
        "alignment": "center"
    },
    "text": {
        "data": "Click Here",
        "size": 36,
        "style": "bold",
        "name": "text1",
        "hOffset": 250,
        "vOffset": 100,
        "alignment": "center",
        "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
    }
}}

 let widgetJson = "{\"widget\": {
 \"debug\": \"on\",
 \"window\": {
 \"title\": \"Sample Konfabulator Widget\", 
 \"name\": \"main_window\", 
 \"width\": 500, 
 \"height\": 500
 }, \"image\": { 
 \"src\": \"Images/Sun.png\",
 \"name\": \"sun1\", 
 \"hOffset\": 250, 
 \"vOffset\": 250, 
 \"alignment\": \"center\"
 }, \"text\": {
 \"data\": \"Click Here\",
 \"size\": 36,
 \"style\": \"bold\", 
 \"name\": \"text1\", 
 \"hOffset\": 250, 
 \"vOffset\": 100, 
 \"alignment\": \"center\",
 \"onMouseUp\": \"sun1.opacity = (sun1.opacity / 100) * 90;\"
 }
}}"

 

> parseJson widgetJson;;
val it : JSValue =
  JSObject
    [(JSString "widget",
      JSObject
        [(JSString "debug", JSString "on");
         (JSString "window",
          JSObject
            [(JSString "title", JSString "Sample Konfabulator Widget");
             (JSString "name", JSString "main_window");
             (JSString "width", JSNumber 500.0);
             (JSString "height", JSNumber 500.0)]);
         (JSString "image",
          JSObject
            [(JSString "src", JSString "Images/Sun.png");
             (JSString "name", JSString "sun1");
             (JSString "hOffset", JSNumber 250.0);
             (JSString "vOffset", JSNumber 250.0);
             (JSString "alignment", JSString "center")]);
         (JSString "text",
          JSObject
            [(JSString "data", JSString "Click Here");
             (JSString "size", JSNumber 36.0);
             (JSString "style", JSString "bold");
             (JSString "name", JSString "text1");
             (JSString "hOffset", JSNumber 250.0);
             (JSString "vOffset", JSNumber 100.0);
             (JSString "alignment", JSString "center");
             (JSString "onMouseUp",
              JSString "sun1.opacity = (sun1.opacity / 100) * 90;")])])]

Ladies and gentlemen, it works!!! I can see some watery eyes out there, and it is ok, building monadic parsers is most definitely an emotional experience!

Make sure to get all the parsers and play with them at https://fssnip.net/
• Parser Monad and combinators
• JSON Parser

Wrapping up

This is just like Lego for functional programmers: from parsing a single character to parsing full JSON strings by “simply” composing pieces of parsers together! Now you understand why I completely forgot why I needed a JSON parser in the first place :-).

That said, and now that we are calming down a little bit, it seems we are still missing an piece – if you compare the result above with the "boring parsing" from Part 1, you will notice we here have just a JSON AST, while there, we ended up with a “real” F# type… I guess we will need to look at that in the next post.

Stay tuned and let me know your comments!

Parsing JSON the fun way series

Part 1: Building a parser from scratch with Dr. Seuss help (part 1)
Part 2: Tricking you into Parser Monads (it's not going to hurt, I promise)
Part 3: The JSON Parser Monad

 

namespace System

val s2cs : (seq<'a> -> 'a list)

Full name: JSONParser.s2cs

Multiple items
module List

from Microsoft.FSharp.Collections

--------------------

type List<'T> =
  | ( [] )
  | ( :: ) of 'T * 'T list
  with
    interface Collections.IEnumerable
    interface Collections.Generic.IEnumerable<'T>
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    member Tail : 'T list
    static member Cons : head:'T * tail:'T list -> 'T list
    static member Empty : 'T list
  end

Full name: Microsoft.FSharp.Collections.List<_>

  type: List<'T>
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'T>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'T>
  implements: Collections.IEnumerable

val ofSeq : seq<'T> -> 'T list

Full name: Microsoft.FSharp.Collections.List.ofSeq

val cs2s : char list -> String

Full name: JSONParser.cs2s

val cs : char list

  type: char list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<char>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<char>
  implements: Collections.IEnumerable

type String =
  class
    new : char -> string
    new : char * int * int -> string
    new : System.SByte -> string
    new : System.SByte * int * int -> string
    new : System.SByte * int * int * System.Text.Encoding -> string
    new : char [] * int * int -> string
    new : char [] -> string
    new : char * int -> string
    member Chars : int -> char
    member Clone : unit -> obj
    member CompareTo : obj -> int
    member CompareTo : string -> int
    member Contains : string -> bool
    member CopyTo : int * char [] * int * int -> unit
    member EndsWith : string -> bool
    member EndsWith : string * System.StringComparison -> bool
    member EndsWith : string * bool * System.Globalization.CultureInfo -> bool
    member Equals : obj -> bool
    member Equals : string -> bool
    member Equals : string * System.StringComparison -> bool
    member GetEnumerator : unit -> System.CharEnumerator
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> System.TypeCode
    member IndexOf : char -> int
    member IndexOf : string -> int
    member IndexOf : char * int -> int
    member IndexOf : string * int -> int
    member IndexOf : string * System.StringComparison -> int
    member IndexOf : char * int * int -> int
    member IndexOf : string * int * int -> int
    member IndexOf : string * int * System.StringComparison -> int
    member IndexOf : string * int * int * System.StringComparison -> int
    member IndexOfAny : char [] -> int
    member IndexOfAny : char [] * int -> int
    member IndexOfAny : char [] * int * int -> int
    member Insert : int * string -> string
    member IsNormalized : unit -> bool
    member IsNormalized : System.Text.NormalizationForm -> bool
    member LastIndexOf : char -> int
    member LastIndexOf : string -> int
    member LastIndexOf : char * int -> int
    member LastIndexOf : string * int -> int
    member LastIndexOf : string * System.StringComparison -> int
    member LastIndexOf : char * int * int -> int
    member LastIndexOf : string * int * int -> int
    member LastIndexOf : string * int * System.StringComparison -> int
    member LastIndexOf : string * int * int * System.StringComparison -> int
    member LastIndexOfAny : char [] -> int
    member LastIndexOfAny : char [] * int -> int
    member LastIndexOfAny : char [] * int * int -> int
    member Length : int
    member Normalize : unit -> string
    member Normalize : System.Text.NormalizationForm -> string
    member PadLeft : int -> string
    member PadLeft : int * char -> string
    member PadRight : int -> string
    member PadRight : int * char -> string
    member Remove : int -> string
    member Remove : int * int -> string
    member Replace : char * char -> string
    member Replace : string * string -> string
    member Split : char [] -> string []
    member Split : char [] * int -> string []
    member Split : char [] * System.StringSplitOptions -> string []
    member Split : string [] * System.StringSplitOptions -> string []
    member Split : char [] * int * System.StringSplitOptions -> string []
    member Split : string [] * int * System.StringSplitOptions -> string []
    member StartsWith : string -> bool
    member StartsWith : string * System.StringComparison -> bool
    member StartsWith : string * bool * System.Globalization.CultureInfo -> bool
    member Substring : int -> string
    member Substring : int * int -> string
    member ToCharArray : unit -> char []
    member ToCharArray : int * int -> char []
    member ToLower : unit -> string
    member ToLower : System.Globalization.CultureInfo -> string
    member ToLowerInvariant : unit -> string
    member ToString : unit -> string
    member ToString : System.IFormatProvider -> string
    member ToUpper : unit -> string
    member ToUpper : System.Globalization.CultureInfo -> string
    member ToUpperInvariant : unit -> string
    member Trim : unit -> string
    member Trim : char [] -> string
    member TrimEnd : char [] -> string
    member TrimStart : char [] -> string
    static val Empty : string
    static member Compare : string * string -> int
    static member Compare : string * string * bool -> int
    static member Compare : string * string * System.StringComparison -> int
    static member Compare : string * string * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
    static member Compare : string * string * bool * System.Globalization.CultureInfo -> int
    static member Compare : string * int * string * int * int -> int
    static member Compare : string * int * string * int * int * bool -> int
    static member Compare : string * int * string * int * int * System.StringComparison -> int
    static member Compare : string * int * string * int * int * bool * System.Globalization.CultureInfo -> int
    static member Compare : string * int * string * int * int * System.Globalization.CultureInfo * System.Globalization.CompareOptions -> int
    static member CompareOrdinal : string * string -> int
    static member CompareOrdinal : string * int * string * int * int -> int
    static member Concat : obj -> string
    static member Concat : obj [] -> string
    static member Concat<'T> : System.Collections.Generic.IEnumerable<'T> -> string
    static member Concat : System.Collections.Generic.IEnumerable<string> -> string
    static member Concat : string [] -> string
    static member Concat : obj * obj -> string
    static member Concat : string * string -> string
    static member Concat : obj * obj * obj -> string
    static member Concat : string * string * string -> string
    static member Concat : obj * obj * obj * obj -> string
    static member Concat : string * string * string * string -> string
    static member Copy : string -> string
    static member Equals : string * string -> bool
    static member Equals : string * string * System.StringComparison -> bool
    static member Format : string * obj -> string
    static member Format : string * obj [] -> string
    static member Format : string * obj * obj -> string
    static member Format : System.IFormatProvider * string * obj [] -> string
    static member Format : string * obj * obj * obj -> string
    static member Intern : string -> string
    static member IsInterned : string -> string
    static member IsNullOrEmpty : string -> bool
    static member IsNullOrWhiteSpace : string -> bool
    static member Join : string * string [] -> string
    static member Join : string * obj [] -> string
    static member Join<'T> : string * System.Collections.Generic.IEnumerable<'T> -> string
    static member Join : string * System.Collections.Generic.IEnumerable<string> -> string
    static member Join : string * string [] * int * int -> string
  end

Full name: System.String

  type: String
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>

type Array =
  class
    member Clone : unit -> obj
    member CopyTo : System.Array * int -> unit
    member CopyTo : System.Array * int64 -> unit
    member GetEnumerator : unit -> System.Collections.IEnumerator
    member GetLength : int -> int
    member GetLongLength : int -> int64
    member GetLowerBound : int -> int
    member GetUpperBound : int -> int
    member GetValue : int [] -> obj
    member GetValue : int -> obj
    member GetValue : int64 -> obj
    member GetValue : int64 [] -> obj
    member GetValue : int * int -> obj
    member GetValue : int64 * int64 -> obj
    member GetValue : int * int * int -> obj
    member GetValue : int64 * int64 * int64 -> obj
    member Initialize : unit -> unit
    member IsFixedSize : bool
    member IsReadOnly : bool
    member IsSynchronized : bool
    member Length : int
    member LongLength : int64
    member Rank : int
    member SetValue : obj * int -> unit
    member SetValue : obj * int [] -> unit
    member SetValue : obj * int64 -> unit
    member SetValue : obj * int64 [] -> unit
    member SetValue : obj * int * int -> unit
    member SetValue : obj * int64 * int64 -> unit
    member SetValue : obj * int * int * int -> unit
    member SetValue : obj * int64 * int64 * int64 -> unit
    member SyncRoot : obj
    static member AsReadOnly<'T> : 'T [] -> System.Collections.ObjectModel.ReadOnlyCollection<'T>
    static member BinarySearch : System.Array * obj -> int
    static member BinarySearch<'T> : 'T [] * 'T -> int
    static member BinarySearch : System.Array * obj * System.Collections.IComparer -> int
    static member BinarySearch<'T> : 'T [] * 'T * System.Collections.Generic.IComparer<'T> -> int
    static member BinarySearch : System.Array * int * int * obj -> int
    static member BinarySearch<'T> : 'T [] * int * int * 'T -> int
    static member BinarySearch : System.Array * int * int * obj * System.Collections.IComparer -> int
    static member BinarySearch<'T> : 'T [] * int * int * 'T * System.Collections.Generic.IComparer<'T> -> int
    static member Clear : System.Array * int * int -> unit
    static member ConstrainedCopy : System.Array * int * System.Array * int * int -> unit
    static member ConvertAll<'TInput,'TOutput> : 'TInput [] * System.Converter<'TInput,'TOutput> -> 'TOutput []
    static member Copy : System.Array * System.Array * int -> unit
    static member Copy : System.Array * System.Array * int64 -> unit
    static member Copy : System.Array * int * System.Array * int * int -> unit
    static member Copy : System.Array * int64 * System.Array * int64 * int64 -> unit
    static member CreateInstance : System.Type * int -> System.Array
    static member CreateInstance : System.Type * int [] -> System.Array
    static member CreateInstance : System.Type * int64 [] -> System.Array
    static member CreateInstance : System.Type * int * int -> System.Array
    static member CreateInstance : System.Type * int [] * int [] -> System.Array
    static member CreateInstance : System.Type * int * int * int -> System.Array
    static member Exists<'T> : 'T [] * System.Predicate<'T> -> bool
    static member Find<'T> : 'T [] * System.Predicate<'T> -> 'T
    static member FindAll<'T> : 'T [] * System.Predicate<'T> -> 'T []
    static member FindIndex<'T> : 'T [] * System.Predicate<'T> -> int
    static member FindIndex<'T> : 'T [] * int * System.Predicate<'T> -> int
    static member FindIndex<'T> : 'T [] * int * int * System.Predicate<'T> -> int
    static member FindLast<'T> : 'T [] * System.Predicate<'T> -> 'T
    static member FindLastIndex<'T> : 'T [] * System.Predicate<'T> -> int
    static member FindLastIndex<'T> : 'T [] * int * System.Predicate<'T> -> int
    static member FindLastIndex<'T> : 'T [] * int * int * System.Predicate<'T> -> int
    static member ForEach<'T> : 'T [] * System.Action<'T> -> unit
    static member IndexOf : System.Array * obj -> int
    static member IndexOf<'T> : 'T [] * 'T -> int
    static member IndexOf : System.Array * obj * int -> int
    static member IndexOf<'T> : 'T [] * 'T * int -> int
    static member IndexOf : System.Array * obj * int * int -> int
    static member IndexOf<'T> : 'T [] * 'T * int * int -> int
    static member LastIndexOf : System.Array * obj -> int
    static member LastIndexOf<'T> : 'T [] * 'T -> int
    static member LastIndexOf : System.Array * obj * int -> int
    static member LastIndexOf<'T> : 'T [] * 'T * int -> int
    static member LastIndexOf : System.Array * obj * int * int -> int
    static member LastIndexOf<'T> : 'T [] * 'T * int * int -> int
    static member Resize<'T> : 'T [] * int -> unit
    static member Reverse : System.Array -> unit
    static member Reverse : System.Array * int * int -> unit
    static member Sort : System.Array -> unit
    static member Sort<'T> : 'T [] -> unit
    static member Sort : System.Array * System.Array -> unit
    static member Sort : System.Array * System.Collections.IComparer -> unit
    static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] -> unit
    static member Sort<'T> : 'T [] * System.Collections.Generic.IComparer<'T> -> unit
    static member Sort<'T> : 'T [] * System.Comparison<'T> -> unit
    static member Sort : System.Array * int * int -> unit
    static member Sort : System.Array * System.Array * System.Collections.IComparer -> unit
    static member Sort<'T> : 'T [] * int * int -> unit
    static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] * System.Collections.Generic.IComparer<'TKey> -> unit
    static member Sort : System.Array * System.Array * int * int -> unit
    static member Sort : System.Array * int * int * System.Collections.IComparer -> unit
    static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] * int * int -> unit
    static member Sort<'T> : 'T [] * int * int * System.Collections.Generic.IComparer<'T> -> unit
    static member Sort : System.Array * System.Array * int * int * System.Collections.IComparer -> unit
    static member Sort<'TKey,'TValue> : 'TKey [] * 'TValue [] * int * int * System.Collections.Generic.IComparer<'TKey> -> unit
    static member TrueForAll<'T> : 'T [] * System.Predicate<'T> -> bool
  end

Full name: System.Array

  type: Array
  implements: ICloneable
  implements: Collections.IList
  implements: Collections.ICollection
  implements: Collections.IEnumerable
  implements: Collections.IStructuralComparable
  implements: Collections.IStructuralEquatable

val ofList : 'T list -> 'T []

Full name: Microsoft.FSharp.Collections.Array.ofList

Multiple items
union case Parser.Parser: (char list -> ('a * char list) list) -> 'a Parser

--------------------

type 'a Parser = | Parser of (char list -> ('a * char list) list)

Full name: JSONParser.Parser<_>

Multiple items
val char : 'T -> char (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.char

--------------------

type char = Char

Full name: Microsoft.FSharp.Core.char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>

  type: 'T list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'T>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'T>
  implements: Collections.IEnumerable

val parse : 'a Parser -> (char list -> ('a * char list) list)

Full name: JSONParser.parse

val p : (char list -> ('a * char list) list)

type ParserBuilder =
  class
    new : unit -> ParserBuilder
    member Bind : p:'c Parser * f:('c -> 'd Parser) -> 'd Parser
    member Return : a:'e -> 'e Parser
    member ReturnFrom : a:'a -> 'a
    member Zero : unit -> 'b Parser
  end

Full name: JSONParser.ParserBuilder

val x : ParserBuilder

member ParserBuilder.Return : a:'e -> 'e Parser

Full name: JSONParser.ParserBuilder.Return

val a : 'e

member ParserBuilder.Bind : p:'c Parser * f:('c -> 'd Parser) -> 'd Parser

Full name: JSONParser.ParserBuilder.Bind

val p : 'c Parser

val f : ('c -> 'd Parser)

val c' : 'c

val cs' : char list

  type: char list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<char>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<char>
  implements: Collections.IEnumerable

member ParserBuilder.Zero : unit -> 'b Parser

Full name: JSONParser.ParserBuilder.Zero

member ParserBuilder.ReturnFrom : a:'a -> 'a

Full name: JSONParser.ParserBuilder.ReturnFrom

val a : 'a

val parser : ParserBuilder

Full name: JSONParser.parser

val item : char Parser

Full name: JSONParser.item

val c : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val sat : (char -> bool) -> char Parser

Full name: JSONParser.sat

val pred : (char -> bool)

val tChar : char -> char Parser

Full name: JSONParser.tChar

val p : 'a Parser

val q : 'a Parser

val x : 'a * char list

val xs : ('a * char list) list

  type: ('a * char list) list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'a * char list>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'a * char list>
  implements: Collections.IEnumerable

val text : char list -> char list Parser

Full name: JSONParser.text

Given a char list, returns a parser that parsers it

val many : 'a Parser -> 'a list Parser

Full name: JSONParser.many

Combines many (0 or more) applications of parser p

val many1 : 'a Parser -> 'a list Parser

Full name: JSONParser.many1

Combines at least one (1 or more) applications of parser p

val r : 'a

val rs : 'a list

  type: 'a list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'a>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'a>
  implements: Collections.IEnumerable

val sepby : 'a Parser -> 'b Parser -> 'a list Parser

Full name: JSONParser.sepby

Combines 0 or more applications of parser p separated by parser sep

val sep : 'b Parser

val sepby1 : 'a Parser -> 'b Parser -> 'a list Parser

Full name: JSONParser.sepby1

Combines 1 or more applications of parser p separated by parser sep

val chainl : 'a Parser -> ('a -> 'a -> 'a) Parser -> 'a -> 'a Parser

Full name: JSONParser.chainl

Chain 0 or more applications of parser p separated by applications of parser op

val op : ('a -> 'a -> 'a) Parser

val chainl1 : 'a Parser -> ('a -> 'a -> 'a) Parser -> 'a Parser

Full name: JSONParser.chainl1

Chain 1 or more applications of parser p separated by applications of parser op

val rest : ('a -> 'a Parser)

val f : ('a -> 'a -> 'a)

val r' : 'a

val isSpace : (char -> bool)

Full name: JSONParser.isSpace

val cs : Set<char>

  type: Set<char>
  implements: IComparable
  implements: Collections.Generic.ICollection<char>
  implements: seq<char>
  implements: Collections.IEnumerable

Multiple items
module Set

from Microsoft.FSharp.Collections

--------------------

type Set<'T (requires comparison)> =
  class
    interface IComparable
    interface Collections.IEnumerable
    interface Collections.Generic.IEnumerable<'T>
    interface Collections.Generic.ICollection<'T>
    new : elements:seq<'T> -> Set<'T>
    member Add : value:'T -> Set<'T>
    member Contains : value:'T -> bool
    override Equals : obj -> bool
    member IsProperSubsetOf : otherSet:Set<'T> -> bool
    member IsProperSupersetOf : otherSet:Set<'T> -> bool
    member IsSubsetOf : otherSet:Set<'T> -> bool
    member IsSupersetOf : otherSet:Set<'T> -> bool
    member Remove : value:'T -> Set<'T>
    member Count : int
    member IsEmpty : bool
    member MaximumElement : 'T
    member MinimumElement : 'T
    static member ( + ) : set1:Set<'T> * set2:Set<'T> -> Set<'T>
    static member ( - ) : set1:Set<'T> * set2:Set<'T> -> Set<'T>
  end

Full name: Microsoft.FSharp.Collections.Set<_>

  type: Set<'T>
  implements: IComparable
  implements: Collections.Generic.ICollection<'T>
  implements: seq<'T>
  implements: Collections.IEnumerable

val ofList : 'T list -> Set<'T> (requires comparison)

Full name: Microsoft.FSharp.Collections.Set.ofList

member Set.Contains : value:'T -> bool

val space : char list Parser

Full name: JSONParser.space

val token : 'a Parser -> 'a Parser

Full name: JSONParser.token

val symb : (char list -> char list Parser)

Full name: JSONParser.symb

val apply : 'a Parser -> (char list -> ('a * char list) list)

Full name: JSONParser.apply

val runParser : 'a Parser -> (seq<char> -> 'a)

Full name: JSONParser.runParser

val failwith : string -> 'T

Full name: Microsoft.FSharp.Core.Operators.failwith

val result : 'a

val isHexDigit : (char -> bool)

Full name: JSONParser.isHexDigit

val ds : Set<char>

  type: Set<char>
  implements: IComparable
  implements: Collections.Generic.ICollection<char>
  implements: seq<char>
  implements: Collections.IEnumerable

val hexDigit : char Parser

Full name: JSONParser.hexDigit

val charToken : (char -> char Parser)

Full name: JSONParser.charToken

val betweenChars : char -> char -> (unit -> 'a Parser) -> 'a Parser

Full name: JSONParser.betweenChars

val c1 : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val c2 : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val f : (unit -> 'a Parser)

val zeroOrOne : 'a list Parser -> 'a list Parser

Full name: JSONParser.zeroOrOne

val p : 'a list Parser

val ret : 'a list

  type: 'a list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'a>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'a>
  implements: Collections.IEnumerable

val q : 'a list Parser

val rp : 'a list

  type: 'a list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'a>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'a>
  implements: Collections.IEnumerable

val rq : 'a list

  type: 'a list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<'a>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<'a>
  implements: Collections.IEnumerable

type JSValue =
  | JSString of string
  | JSNumber of float
  | JSObject of (JSValue * JSValue) list
  | JSArray of JSValue list
  | JSBool of bool
  | JSNull

Full name: JSONParser.JSValue

  type: JSValue
  implements: IEquatable<JSValue>
  implements: Collections.IStructuralEquatable
  implements: IComparable<JSValue>
  implements: IComparable
  implements: Collections.IStructuralComparable

union case JSValue.JSString: string -> JSValue

Multiple items
val string : 'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------

type string = String

Full name: Microsoft.FSharp.Core.string

  type: string
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>

union case JSValue.JSNumber: float -> JSValue

Multiple items
val float : 'T -> float (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.float

--------------------

type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>

  type: float<'Measure>
  implements: IComparable
  implements: IConvertible
  implements: IFormattable
  implements: IComparable<float<'Measure>>
  implements: IEquatable<float<'Measure>>
  inherits: ValueType

--------------------

type float = Double

Full name: Microsoft.FSharp.Core.float

  type: float
  implements: IComparable
  implements: IFormattable
  implements: IConvertible
  implements: IComparable<float>
  implements: IEquatable<float>
  inherits: ValueType

union case JSValue.JSObject: (JSValue * JSValue) list -> JSValue

union case JSValue.JSArray: JSValue list -> JSValue

union case JSValue.JSBool: bool -> JSValue

type bool = Boolean

Full name: Microsoft.FSharp.Core.bool

  type: bool
  implements: IComparable
  implements: IConvertible
  implements: IComparable<bool>
  implements: IEquatable<bool>
  inherits: ValueType

union case JSValue.JSNull: JSValue

val undefined<'a> : 'a

Full name: JSONParser.undefined

module Unchecked

from Microsoft.FSharp.Core.Operators

val defaultof<'T> : 'T

Full name: Microsoft.FSharp.Core.Operators.Unchecked.defaultof

val jsString' : JSValue Parser

Full name: JSONParser.jsString'

val jsNumber' : JSValue Parser

Full name: JSONParser.jsNumber'

val jsBool' : JSValue Parser

Full name: JSONParser.jsBool'

val jsNull' : JSValue Parser

Full name: JSONParser.jsNull'

val jsValue' : JSValue Parser

Full name: JSONParser.jsValue'

val jsElements' : JSValue list Parser

Full name: JSONParser.jsElements'

val jsArray' : JSValue Parser

Full name: JSONParser.jsArray'

val jsMembers' : (JSValue * JSValue) list Parser

Full name: JSONParser.jsMembers'

val jsPair' : (JSValue * JSValue) Parser

Full name: JSONParser.jsPair'

val jsObject' : JSValue Parser

Full name: JSONParser.jsObject'

val jsNull : JSValue Parser

Full name: JSONParser.jsNull

val nullLiteral : char list

  type: char list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<char>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<char>
  implements: Collections.IEnumerable

val jsBool : JSValue Parser

Full name: JSONParser.jsBool

val trueLit : char list

  type: char list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<char>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<char>
  implements: Collections.IEnumerable

val falseLit : char list

  type: char list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<char>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<char>
  implements: Collections.IEnumerable

val jsNumber'' : JSValue Parser

Full name: JSONParser.jsNumber''

val digitsParser : char list Parser

val intParser : char list Parser

val fracParser : char list Parser

val expParser : char list Parser

val jsNumber : JSValue Parser

Full name: JSONParser.jsNumber

type Char =
  struct
    member CompareTo : obj -> int
    member CompareTo : char -> int
    member Equals : obj -> bool
    member Equals : char -> bool
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> System.TypeCode
    member ToString : unit -> string
    member ToString : System.IFormatProvider -> string
    static val MaxValue : char
    static val MinValue : char
    static member ConvertFromUtf32 : int -> string
    static member ConvertToUtf32 : char * char -> int
    static member ConvertToUtf32 : string * int -> int
    static member GetNumericValue : char -> float
    static member GetNumericValue : string * int -> float
    static member GetUnicodeCategory : char -> System.Globalization.UnicodeCategory
    static member GetUnicodeCategory : string * int -> System.Globalization.UnicodeCategory
    static member IsControl : char -> bool
    static member IsControl : string * int -> bool
    static member IsDigit : char -> bool
    static member IsDigit : string * int -> bool
    static member IsHighSurrogate : char -> bool
    static member IsHighSurrogate : string * int -> bool
    static member IsLetter : char -> bool
    static member IsLetter : string * int -> bool
    static member IsLetterOrDigit : char -> bool
    static member IsLetterOrDigit : string * int -> bool
    static member IsLowSurrogate : char -> bool
    static member IsLowSurrogate : string * int -> bool
    static member IsLower : char -> bool
    static member IsLower : string * int -> bool
    static member IsNumber : char -> bool
    static member IsNumber : string * int -> bool
    static member IsPunctuation : char -> bool
    static member IsPunctuation : string * int -> bool
    static member IsSeparator : char -> bool
    static member IsSeparator : string * int -> bool
    static member IsSurrogate : char -> bool
    static member IsSurrogate : string * int -> bool
    static member IsSurrogatePair : string * int -> bool
    static member IsSurrogatePair : char * char -> bool
    static member IsSymbol : char -> bool
    static member IsSymbol : string * int -> bool
    static member IsUpper : char -> bool
    static member IsUpper : string * int -> bool
    static member IsWhiteSpace : char -> bool
    static member IsWhiteSpace : string * int -> bool
    static member Parse : string -> char
    static member ToLower : char -> char
    static member ToLower : char * System.Globalization.CultureInfo -> char
    static member ToLowerInvariant : char -> char
    static member ToString : char -> string
    static member ToUpper : char -> char
    static member ToUpper : char * System.Globalization.CultureInfo -> char
    static member ToUpperInvariant : char -> char
    static member TryParse : string * char -> bool
  end

Full name: System.Char

  type: Char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

Multiple overloads
Char.IsDigit(c: char) : bool
Char.IsDigit(s: string, index: int) : bool

val result : char list

  type: char list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<char>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<char>
  implements: Collections.IEnumerable

type Double =
  struct
    member CompareTo : obj -> int
    member CompareTo : float -> int
    member Equals : obj -> bool
    member Equals : float -> bool
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> System.TypeCode
    member ToString : unit -> string
    member ToString : string -> string
    member ToString : System.IFormatProvider -> string
    member ToString : string * System.IFormatProvider -> string
    static val MinValue : float
    static val MaxValue : float
    static val Epsilon : float
    static val NegativeInfinity : float
    static val PositiveInfinity : float
    static val NaN : float
    static member IsInfinity : float -> bool
    static member IsNaN : float -> bool
    static member IsNegativeInfinity : float -> bool
    static member IsPositiveInfinity : float -> bool
    static member Parse : string -> float
    static member Parse : string * System.Globalization.NumberStyles -> float
    static member Parse : string * System.IFormatProvider -> float
    static member Parse : string * System.Globalization.NumberStyles * System.IFormatProvider -> float
    static member TryParse : string * float -> bool
    static member TryParse : string * System.Globalization.NumberStyles * System.IFormatProvider * float -> bool
  end

Full name: System.Double

  type: Double
  implements: IComparable
  implements: IFormattable
  implements: IConvertible
  implements: IComparable<float>
  implements: IEquatable<float>
  inherits: ValueType

Multiple overloads
Double.Parse(s: string) : float
Double.Parse(s: string, provider: IFormatProvider) : float
Double.Parse(s: string, style: Globalization.NumberStyles) : float
Double.Parse(s: string, style: Globalization.NumberStyles, provider: IFormatProvider) : float

val jsString : JSValue Parser

Full name: JSONParser.jsString

val isChar : (char -> bool)

val isEscChar : (char -> bool)

val replaceEscChar : (char -> char)

val other : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val escChars : char Parser

val uniChars : char Parser

val d1 : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val d2 : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val d3 : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val d4 : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val r : char

  type: char
  implements: IComparable
  implements: IConvertible
  implements: IComparable<char>
  implements: IEquatable<char>
  inherits: ValueType

val s : String

  type: String
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>

type Byte =
  struct
    member CompareTo : obj -> int
    member CompareTo : System.Byte -> int
    member Equals : obj -> bool
    member Equals : System.Byte -> bool
    member GetHashCode : unit -> int
    member GetTypeCode : unit -> System.TypeCode
    member ToString : unit -> string
    member ToString : string -> string
    member ToString : System.IFormatProvider -> string
    member ToString : string * System.IFormatProvider -> string
    static val MaxValue : System.Byte
    static val MinValue : System.Byte
    static member Parse : string -> System.Byte
    static member Parse : string * System.Globalization.NumberStyles -> System.Byte
    static member Parse : string * System.IFormatProvider -> System.Byte
    static member Parse : string * System.Globalization.NumberStyles * System.IFormatProvider -> System.Byte
    static member TryParse : string * System.Byte -> bool
    static member TryParse : string * System.Globalization.NumberStyles * System.IFormatProvider * System.Byte -> bool
  end

Full name: System.Byte

  type: Byte
  implements: IComparable
  implements: IFormattable
  implements: IConvertible
  implements: IComparable<byte>
  implements: IEquatable<byte>
  inherits: ValueType

Multiple overloads
Byte.Parse(s: string) : byte
Byte.Parse(s: string, provider: IFormatProvider) : byte
Byte.Parse(s: string, style: Globalization.NumberStyles) : byte
Byte.Parse(s: string, style: Globalization.NumberStyles, provider: IFormatProvider) : byte

namespace System.Globalization

type NumberStyles =
  | None = 0
  | AllowLeadingWhite = 1
  | AllowTrailingWhite = 2
  | AllowLeadingSign = 4
  | AllowTrailingSign = 8
  | AllowParentheses = 16
  | AllowDecimalPoint = 32
  | AllowThousands = 64
  | AllowExponent = 128
  | AllowCurrencySymbol = 256
  | AllowHexSpecifier = 512
  | Integer = 7
  | HexNumber = 515
  | Number = 111
  | Float = 167
  | Currency = 383
  | Any = 511

Full name: System.Globalization.NumberStyles

  type: Globalization.NumberStyles
  inherits: Enum
  inherits: ValueType

field Globalization.NumberStyles.HexNumber = 515

val chars : char list Parser

val jsValue : JSValue Parser

Full name: JSONParser.jsValue

val jsElements : JSValue list Parser

Full name: JSONParser.jsElements

val jsArray : JSValue Parser

Full name: JSONParser.jsArray

val values : JSValue list

  type: JSValue list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<JSValue>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<JSValue>
  implements: Collections.IEnumerable

val jsMembers : (JSValue * JSValue) list Parser

Full name: JSONParser.jsMembers

val jsPair : (JSValue * JSValue) Parser

Full name: JSONParser.jsPair

val key : JSValue

  type: JSValue
  implements: IEquatable<JSValue>
  implements: Collections.IStructuralEquatable
  implements: IComparable<JSValue>
  implements: IComparable
  implements: Collections.IStructuralComparable

val value : JSValue

  type: JSValue
  implements: IEquatable<JSValue>
  implements: Collections.IStructuralEquatable
  implements: IComparable<JSValue>
  implements: IComparable
  implements: Collections.IStructuralComparable

val jsObject : JSValue Parser

Full name: JSONParser.jsObject

val members : (JSValue * JSValue) list

  type: (JSValue * JSValue) list
  implements: Collections.IStructuralEquatable
  implements: IComparable<List<JSValue * JSValue>>
  implements: IComparable
  implements: Collections.IStructuralComparable
  implements: Collections.Generic.IEnumerable<JSValue * JSValue>
  implements: Collections.IEnumerable

val parseJson : (string -> JSValue)

Full name: JSONParser.parseJson

val widgetJson : string

Full name: JSONParser.widgetJson

  type: string
  implements: IComparable
  implements: ICloneable
  implements: IConvertible
  implements: IComparable<string>
  implements: seq<char>
  implements: Collections.IEnumerable
  implements: IEquatable<string>