Infers.Toys Library ReferenceSynopsisnamespace Infers.Toys [<AutoOpen>] module AsPairs = type AsPairs<'p,'t> with member Extract: from: 't * into: array<obj> -> unit member Create: from: array<obj> -> 't member Overwrite: record: Record<'t> * into: 't * from: array<obj> -> unit [<AutoOpen>] module Basic = type Eq<'x, 'y> type Eq<'x, 'y, 'z> type Basic = inherit Rules new: unit -> Basic static member Eq'2: unit -> Eq<'x, 'x> static member Eq'3: unit -> Eq<'x, 'x, 'x> static member Choice1Of2: 'x1 -> Choice<'x1, 'x2> static member Choice2Of2: 'x2 -> Choice<'x1, 'x2> static member Choice1Of3: 'x1 -> Choice<'x1, 'x2, 'x3> static member Choice2Of3: 'x2 -> Choice<'x1, 'x2, 'x3> static member Choice3Of3: 'x3 -> Choice<'x1, 'x2, 'x3> [<AutoOpen>] module Bitwise = type Bitwise<'b, 't> = { ToBits: 't -> 'b OfBits: 'b -> 't } type Bitwise = inherit Rules new: unit -> Bitwise static member Bool: Bitwise<uint8, bool> static member Char: Bitwise<int16, char> static member Float32: Bitwise<int32, float32> static member Float64: Bitwise<int64, float> static member Int8: Bitwise<uint8, int8> static member UInt16: Bitwise<int16, uint16> static member UInt32: Bitwise<int32, uint32> static member UInt64: Bitwise<int64, uint64> [<AutoOpen>] module Elems = val elems<'h, 'w> : 'w -> array<'h> val children: 'w -> array<'w> val elemsDn<'h, 'w> : 'w -> seq<'h> val universe: 'w -> seq<'w> val para: ('w -> array<'r> -> 'r) -> 'w -> 'r val subst<'h, 'w> : ('h -> 'h) -> 'w -> 'w val descend: ('w -> 'w) -> 'w -> 'w val substUp<'h, 'w> : ('h -> 'h) -> 'w -> 'w val transform: ('w -> 'w) -> 'w -> 'w val rewrite: ('w -> option<'w>) -> 'w -> 'w [<AutoOpen>] module Flatten = val flatten: 'xxs -> seq<'x> when 'xxs :> seq<_> type Flatten = inherit Rules new: unit -> Flatten static member Flat: unit -> ('xs -> seq<'x>) when 'xs :> seq<'x> static member Nested: ('xss -> seq<'x>) -> ('xsss -> seq<'x>) when 'xsss :> seq<'xss> [<AutoOpen>] module GFlip = val gflip: ('a -> 'b) -> ('c -> 'd) [<AutoOpen>] module GUncurry = val guncurry: ('a -> 'b) -> ('c -> 'd) [<AutoOpen>] module Integral = type Integral<'t> = { IsSigned: bool IsBigInt: bool Suffices: list<string> ToInt64: 't -> int64 OfInt64: int64 -> 't ToUInt64: 't -> uint64 OfUInt64: uint64 -> 't ToBigInt: 't -> bigint OfBigInt: bigint -> 't } type Integral = inherit Rules new: unit -> Integral static member Int8: Integral<int8> static member Int16: Integral<int16> static member Int32: Integral<int32> static member Int64: Integral<int64> static member UInt8: Integral<uint8> static member UInt16: Integral<uint16> static member UInt32: Integral<uint32> static member UInt64: Integral<uint64> static member NativeInt: Integral<nativeint> static member UNativeInt: Integral<unativeint> static member BigInt: Integral<bigint> [<AutoOpen>] module Json = type Obj = Map<string, Value> and Value = | Obj of Obj | List of list<Value> | String of string | Number of string | Bool of bool | Nil type Is<'t> = | Is val toString: Value -> string val toDoc: Value -> Doc val ofString: string -> Value val tryOfString: string -> Choice<Value, string> val toJson<'t> : 't -> Value val toJsonString<'t> : 't -> string val ofJson<'t> : Value -> 't val tryOfJson<'t> : Value -> Choice<'t, string> val ofJsonString<'t> : string -> 't val tryOfJsonString<'t> : string -> Choice<'t, string> [<AutoOpen>] module MayBeMutable = val mayBeMutable<'t> : bool [<AutoOpen>] module PU = val pickle<'x> : 'x -> array<byte> val unpickle<'x> : array<byte> -> 'x type PU<'x> type PUP<'e, 'r, 'o, 't> type PUS<'p, 'o, 't> type PU = inherit Rules new: unit -> PU static member Rec: unit -> Rec<PU<'t>> static member Unit: PU<unit> static member UInt8: PU<uint8> static member Int16: PU<int16> static member Int32: PU<int32> static member Int64: PU<int64> static member Bitwise: Bitwise<'b,'t> * PU<'b> -> PU<'t> static member String: PU<string> static member Elem: Elem<'e,'r,'o,'t> * PU<'e> -> PUP<'e,'r,'o,'t> static member Pair: PUP< 'e , Pair<'e,'r>,'o,'t> * PUP< 'r , 'r ,'o,'t> -> PUP<Pair<'e,'r>, Pair<'e,'r>,'o,'t> static member Tuple: Tuple<'t> * AsPairs<'p,'o,'t> * PUP<'p,'p,'o,'t> -> PU<'t> static member Record: Record<'t> * AsPairs<'p,'o,'t> * PUP<'p,'p,'o,'t> -> PU<'t> static member Case: Case<Empty,'o,'t> -> PUS<Empty,'o,'t> static member Case: Case<'p,'o,'t> * PUP<'p,'p,'o,'t> -> PUS<'p,'o,'t> static member Choice: PUS< 'p , Choice<'p,'o>,'t> * PUS< 'o , 'o ,'t> -> PUS<Choice<'p,'o>, Choice<'p,'o>,'t> static member Sum: AsChoices<'s,'t> * PUS<'s,'s,'t> -> PU<'t> [<AutoOpen>] module Pretty = val pretty: 'x -> Doc val show: 'x -> string type Pretty<'t> = 't -> Doc type PrettyO<'t> type PrettyP<'e,'r,'o,'t> type PrettyS<'p,'o,'t> type Pretty = inherit Rules new: unit -> Pretty static member Enter: PrettyO<'t> -> Pretty<'t> static member Rec: unit -> Rec<PrettyO<'t>> static member Unit: PrettyO<unit> static member Bool: PrettyO<bool> static member Integral: Integral<'t> -> PrettyO<'t> static member Float32: PrettyO<float32> static member Float64: PrettyO<float> static member Char: PrettyO<char> static member String: PrettyO<string> static member Option: PrettyO<'t> -> PrettyO<option<'t>> static member Ref: PrettyO<'t> -> PrettyO<ref<'t>> static member List: PrettyO<'t> -> PrettyO<list<'t>> static member Array: PrettyO<'t> -> PrettyO<array<'t>> static member Item: Item<'e,'r,'t> * PrettyO<'e> -> PrettyP<'e,'r,'t,'t> static member Labelled: Labelled<'e,'r,'o,'t> * PrettyO<'e> -> PrettyP<'e,'r,'o,'t> static member Pair: PrettyP< 'e , Pair<'e,'r>,'o,'t> * PrettyP< 'r , 'r ,'o,'t> -> PrettyP<Pair<'e,'r>, Pair<'e,'r>,'o,'t> static member Product: AsPairs<'p,'t,'t> * PrettyP<'p,'p,'t,'t> -> PrettyO<'t> static member Case: Case<Empty,'o,'t> -> PrettyS<Empty,'o,'t> static member Case: Case<'p,'o,'t> * PrettyP<'p,'p,'o,'t> -> PrettyS<'p,'o,'t> static member Choice: PrettyS< 'p , Choice<'p,'o>,'t> * PrettyS< 'o , 'o ,'t> -> PrettyS<Choice<'p,'o>, Choice<'p,'o>,'t> static member Sum: AsChoices<'s,'t> * PrettyS<'s,'s,'t> -> PrettyO<'t> module Product = val get: 'p -> 'e val iter: 'handlers -> 'p -> unit val init: 'handlers -> 'p val fold: 'handlers -> 'p -> 's -> 's [<AutoOpen>] module Rec = type RecVal<'t> = inherit Rec<'t> val mutable Rec: 't new: (RecVal<'t> -> 't) -> RecVal<'t> val recVal<'t> : (RecVal<'t> -> 't) -> Rec<'t> type RecP<'e, 'r, 'o, 't> type Rec = inherit Rules new: unit -> Rec static member Fun: unit -> Rec<'x -> 'y> static member Func0: unit -> Rec<Func<'x>> static member Func1: unit -> Rec<Func<'x,'y>> static member Func2: unit -> Rec<Func<'x,'y,'z>> static member Elem: Elem<'e,'r,'o,'t> * Rec<'e> -> RecP<'e,'r,'o,'t> static member Pair: RecP< 'e , Pair<'e,'r>,'o,'t> * RecP< 'r , 'r ,'o,'t> -> RecP<Pair<'e,'r>, Pair<'e,'r>,'o,'t> static member Product: AsPairs<'p,'o,'t> * RecP<'p,'p,'o,'t> -> Rec<'t> [<AutoOpen>] module SomeOf = val someOf<'t> : 't module Zipper = [<AbstractClass>] type Zipper<'w> = abstract DownHeadAny: unit -> option<Zipper<'w>> abstract DownHeadThe: unit -> option<Zipper<'w, 'w>> abstract DownLastAny: unit -> option<Zipper<'w>> abstract DownLastThe: unit -> option<Zipper<'w, 'w>> abstract NextAny: unit -> option<Zipper<'w>> abstract NextThe: unit -> option<Zipper<'w, 'w>> abstract PrevAny: unit -> option<Zipper<'w>> abstract PrevThe: unit -> option<Zipper<'w, 'w>> abstract Up: unit -> option<Zipper<'w>> abstract GetObj: unit -> obj [<AbstractClass>] and [<AbstractClass>] Zipper<'w, 'h> = inherit Zipper<'w> abstract Get: unit -> 'h abstract Set: 'h -> Zipper<'w, 'h> type Zipper = inherit Rules new: unit -> Zipper val fromZipper: Zipper<'w> -> 'w val toZipperAny: 'w -> Zipper<'w> val getAny: Zipper<'w> -> option<'h> val setAny: 'h -> Zipper<'w> -> option<Zipper<'w>> val downHeadAny: Zipper<'w> -> option<Zipper<'w>> val downLastAny: Zipper<'w> -> option<Zipper<'w>> val upAny: Zipper<'w> -> option<Zipper<'w>> val nextAny: Zipper<'w> -> option<Zipper<'w>> val prevAny: Zipper<'w> -> option<Zipper<'w>> val toZipperThe: 'w -> Zipper<'w, 'w> val getThe: Zipper<'w, 'w> -> 'w val setThe: 'w -> Zipper<'w, 'w> -> Zipper<'w, 'w> val downHeadThe: Zipper<'w> -> option<Zipper<'w, 'w>> val downLastThe: Zipper<'w> -> option<Zipper<'w, 'w>> val upThe: Zipper<'w> -> option<Zipper<'w, 'w>> val nextThe: Zipper<'w> -> option<Zipper<'w, 'w>> val prevThe: Zipper<'w> -> option<Zipper<'w, 'w>> val mapBottomUpThe: ('w -> 'w) -> Zipper<'w, 'w> -> Zipper<'w, 'w> val mapTopDownThe: ('w -> 'w) -> Zipper<'w, 'w> -> Zipper<'w, 'w> Descriptionnamespace Infers.Toys [<AutoOpen>] module Basic = type Eq<'x, 'y> Equality: type Eq<'x, 'y, 'z> Ternary equality: type Basic = Basic rules for logic programming: equality ( [<AutoOpen>] module Bitwise = type Bitwise<'b, 't> = { Isomorphism between It would be more logical to map bitwise types to unsigned integral types. However, except for type Bitwise = [<AutoOpen>] module Elems = Provides generic functions similar to, but not exactly like, Neil Mitchell's Uniplate. The operations in the type SoP<...> = | Case1 of Elem<I1, J1> * ... * Elem<I1, Jm1> | ... | CaseN of Elem<In, J1> * ... * Elem<Im, Jmn> where the In the documentation we will make use of the following type: type BinTr<'x> = | Lf | Br of BinTr<'x> * 'x * BinTr<'x> Note that val elems<'h, 'w> : 'w -> array<'h> By design, elems<int, _> Lf = [||] elems<int, _> (Br (Lf, 1, Lf)) = [|1|] elems<int, _> (Br (Lf, (1, 2), Lf)) = [||] elems<int * int, _> (Br (Lf, (1, 2), Lf)) = [|(1, 2)|] Note that any type of elements val children: 'w -> array<'w> val elemsDn<'h, 'w> : 'w -> seq<'h> For example, elemsDn<int, _> (Br (Br (Lf, 1, Br (Lf, 2, Lf)), 3, Br (Lf, 4, Lf))) gives the sequence seq [3; 1; 2; 4] val universe: 'w -> seq<'w> For example, universe (Br (Br (Lf, 1, Br (Lf, 2, Lf)), 3, Br (Lf, 4, Lf))) gives the sequence seq [Br (Br (Lf, 1, Br (Lf, 2, Lf)), 3, Br (Lf, 4, Lf)) Br (Lf, 1, Br (Lf, 2, Lf)) Br (Lf, 4, Lf) Lf Br (Lf, 2, Lf) Lf Lf Lf Lf] val para: ('w -> array<'r> -> 'r) -> 'w -> 'r For example, let height t = para (fun _ hs -> Array.fold max 0 hs + 1) t computes the "height" of any recursive union or record type. For example, height Lf = 1 height [] = 1 height ("Non", ("recursive", "type")) = 1 height (Br (Lf, 1, Br (Lf, 2, Lf))) = 3 height [1;1;1] = 4 val subst<'h, 'w> : ('h -> 'h) -> 'w -> 'w val descend: ('w -> 'w) -> 'w -> 'w val substUp<'h, 'w> : ('h -> 'h) -> 'w -> 'w For example, substUp ((+) 1) [1; 2; 3] = [2; 3; 4] and substUp (fun xs -> 0::xs) [1; 2; 3] = [1; 0; 2; 0; 3; 0] val transform: ('w -> 'w) -> 'w -> 'w For example, given type of a binary trees type BinTr<'x> = | Lf | Br of BinTr<'x> * 'x * BinTr<'x> we can write a function to mirror trees let mirror bt = transform <| function Lf -> Lf | Br (l, x, r) -> Br (r, x, l) <| bt Now Br (Br (Lf, 1, Lf), 2, Br (Br (Lf, 3, Lf), 4, Lf)) |> mirror evaluates to Br (Br (Lf, 4, Br (Lf, 3, Lf)), 2, Br (Lf, 1, Lf)) val rewrite: ('w -> option<'w>) -> 'w -> 'w Transforms with given partial function until a fixed point is reached. [<AutoOpen>] module GFlip = val gflip: ('a -> 'b) -> ('c -> 'd) Derives a function that reorders, i.e. "generically" flips, the arguments of a given function. For example, Note that if the arguments do not have unique types the resulting ordering may not be the one you want. Due to limitations of the F# type system, the function must have a monomorphic type. If the function does not have a monomorphic type, you must constrain it. [<AutoOpen>] module GUncurry = val guncurry: ('a -> 'b) -> ('c -> 'd) Derives a function that uncurries a given n-ary curried function. For example, Due to limitations of the F# type system, the function must have a monomorphic type. If the function does not have a monomorphic type, you must constrain it. [<AutoOpen>] module Integral = type Integral<'t> = Provides information on the integral type [<AutoOpen>] module Json = Provides a mapping between a subset of F# and JSON values. The goal is to make it possible to map typical existing JSON APIs to F# types and to specify new JSON APIs using F# types. Note that the goal here isn't to provide an encoding of all F# types in JSON. Such encodings can be useful for the internal communication or persistence of an application, but tend not to work well for mapping existing JSON APIs or for specifying new APIs to be used by external applications. Neither is the goal to support entirely arbitrary JSON mapping, although one can always fall back to the JSON AST, but to rather provide a mapping that should lead to usable F# types when mapping typical APIs. A mapping is always specified as a F# type. In the following we specify the (almost) bidirectional translation of the supported subset of F# values to JSON values. Simple values are translated as is: [< true >] ~ true [< false >] ~ false [< number:int >] ~ number [< number:float >] ~ number [< number:int64 >] ~ number [< "string" >] ~ "string" Special numbers are translated to null and the translation is obviously not bidirectional: [< nan:float>] ~ null [< infinity:float>] ~ null [< -infinity:float>] ~ null Note that special numbers do not have standard representation in JSON and the above treatment of special numbers corresponds to what JavaScript's The unit value, [< () >] ~ null Records are translated to objects where record fields of [< {l1 = v1; ...; lN = vN} >] ~ {[< "l1": v1 >], ..., [< "lN": vN >]} [< "l": None >] ~ [< "l": Some v >] ~ "l": [< v >] [< "l": v >] ~ "l": [< v >] Note that Tuples are translated to fixed length arrays with non-uniform types while lists and arrays are translated to arrays with uniform type: [< (v1, ..., vN) >] ~ [[< v1 >], ..., [< vN >]] [< [v1, ..., vN] >] ~ [[< v1 >], ..., [< vN >]] [< [|v1, ..., vN|] >] ~ [[< v1 >], ..., [< vN >]] Union cases are translated by ignoring the union constructor [< C v >] ~ [< v >] [< C (l1 = v1, ..., lN = vN) >] ~ {[< "l1": v1 >], ..., [< "lN": vN >]} That union constructors are ignored makes it possible to use them in encodings of both discriminated and non-discriminated unions. For the purpose of encoding typical discriminated unions, the special [< Is<TypeName> >] ~ "TypeName" Maps and dictionaries whose keys are strings are translated to objects: [< map [("k", v); ...] >] ~ {"k": [< v >], ...} [< dict [("k", v); ...] >] ~ {"k": [< v >], ...} Finally, JSON AST values are traslated to JSON: [< Obj map >] ~ [< map >] [< List list >] ~ [< list >] [< String "string" >] ~ "string" [< Number "number" >] ~ number [< Bool bool >] ~ [< bool >] [< Nil >] ~ null type Obj = Map<string, Value> Represents a Json object. and Value = | Obj of Obj | List of list<Value> | String of string | Number of string | Bool of bool | Nil Represents a Json value. [<AutoOpen>] module MayBeMutable = val mayBeMutable<'t> : bool Determines whether a value of the given type may contain mutable objects. [<AutoOpen>] module PU = This is a toy example of a binary pickler / unpickler. This can handle integral types, floats, strings, tuples, records, and union types. Recursive types, such as lists, and recursive values, via records, are supported. Other types, including arbitrary classes or structs, are not supported. This could be improved in various ways. Examples: - Pickles do not contain any error checking information. It would be straighforward to add, for example, a hash of the type structure to the beginning of the pickle and verify it when unpickling to help to detect type errors. - Support for various special types such as arrays and refs is not implemented. Such support could be added in a straightforward manner. - Lists are pickled via naive recursive encoding. Lists could be implemented via (not yet implemented) array support. Perhaps the main point here is that it doesn't really take all that much code to implement a fairly powerful pickler. val pickle<'x> : 'x -> array<byte> Converts the given value to an array of bytes. val unpickle<'x> : array<byte> -> 'x module Product = Generic functions for ad hoc record manipulation. val get: 'p -> 'e Gets an element of type For example, get (1, "a", true) |> printf "%s" prints val iter: 'handlers -> 'p -> unit Iterates over the elements of the product of type Each handler function must have a type of one of the forms 'e -> unit int -> 'e -> unit string -> 'e -> unit int -> string -> 'e -> unit where the type Only records and single case union types have labeled elements. The handler is chosen by attempting to get an element of one of the above types from the handlers product. For example, iter (printf "%s", printf "%1.1f", printf "%d") (1, "x", 2.0) prints val init: 'handlers -> 'p Creates a value of the given product of type Each handler function or value must have a type of one of the forms 'e int -> 'e string -> 'e int -> string -> 'e where the type Only records and single case union types have labeled elements. The handler is chosen by attempting to get an element of one of the above types from the handlers product. For example, init (sprintf "%d") : string * string * string returns the tuple val fold: 'handlers -> 'p -> 's -> 's Fold over the elements of the product of type Each handler function must have a type of one of the forms 'e -> 's -> 's int -> 'e -> 's -> 's string -> 'e -> 's -> 's int -> string -> 'e -> 's -> 's where Only records and single case union types have labeled elements. The handler is chosen by attempting to get an element of one of the above types from the handlers product. For example, iter (sprintf "%s" >> (+), sprintf "%1.1f" >> (+), sprintf "%d" >> (+)) (1, "x", 2.0) returns [<AutoOpen>] module Rec = type RecVal<'t> = Combination of val mutable Rec: 't This is initially default initialized, but may later be written with a value of type new: (RecVal<'t> -> 't) -> RecVal<'t> val recVal<'t> : (RecVal<'t> -> 't) -> Rec<'t> Conveniently creates a The given function should delegate to static member Fun () = recVal <| fun r -> fun x -> r.Rec x Note that the above does not read static member Fun () = recVal <| fun r -> r.Rec : _ -> _ reads type Rec = Rules for computing fixed points over products, single case union types (aka newtypes) and functions. Consider the following toy example: type Fib () = inherit Rules () static member fib (fib: int -> int) : int -> int = fun n -> if n < 2 then n else fib (n-1) + fib (n-2) An attempt to We can make type [<Rec>] Fib () = inherit Rules () static member fib (fib: int -> int) : int -> int = fun n -> if n < 2 then n else fib (n-1) + fib (n-2) Now Of course, the above is very much a toy example. One usually uses [<AutoOpen>] module SomeOf = module Zipper = |