val a : int
Full name: index.a
val b : float
Full name: index.b
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = System.Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
val mutable c : int
Full name: index.c
val r : int ref
Full name: index.r
Multiple items
val ref : value:'T -> 'T ref
Full name: Microsoft.FSharp.Core.Operators.ref
--------------------
type 'T ref = Ref<'T>
Full name: Microsoft.FSharp.Core.ref<_>
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Multiple items
type Point =
new : x:int * y:int -> Point
member X : int
member Y : int
Full name: index.Point
--------------------
new : x:int * y:int -> Point
val x : int
Multiple items
val int : value:'T -> int (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.int
--------------------
type int = int32
Full name: Microsoft.FSharp.Core.int
--------------------
type int<'Measure> = int
Full name: Microsoft.FSharp.Core.int<_>
val y : int
member Point.X : int
Full name: index.Point.X
member Point.Y : int
Full name: index.Point.Y
val index : int
val mutable index : int
Full name: index.index
val myFunction : x:int -> y:int -> int
Full name: index.MyMod.myFunction
val myFunction2 : x:int -> y:int -> int
Full name: index.MyMod.myFunction2
val privateFunction : (int -> int)
val z : int
val highOrderFunction : f:('a -> 'b) -> y:'a -> 'b
Full name: index.MyMod.highOrderFunction
val f : ('a -> 'b)
val y : 'a
val recursiveFuncion : x:int -> int
Full name: index.MyMod.recursiveFuncion
val memoizeFunction : (int -> int)
Full name: index.MyMod.memoizeFunction
val cache : System.Collections.Generic.Dictionary<int,int>
namespace System
namespace System.Collections
namespace System.Collections.Generic
Multiple items
type Dictionary<'TKey,'TValue> =
new : unit -> Dictionary<'TKey, 'TValue> + 5 overloads
member Add : key:'TKey * value:'TValue -> unit
member Clear : unit -> unit
member Comparer : IEqualityComparer<'TKey>
member ContainsKey : key:'TKey -> bool
member ContainsValue : value:'TValue -> bool
member Count : int
member GetEnumerator : unit -> Enumerator<'TKey, 'TValue>
member GetObjectData : info:SerializationInfo * context:StreamingContext -> unit
member Item : 'TKey -> 'TValue with get, set
...
nested type Enumerator
nested type KeyCollection
nested type ValueCollection
Full name: System.Collections.Generic.Dictionary<_,_>
--------------------
System.Collections.Generic.Dictionary() : unit
System.Collections.Generic.Dictionary(capacity: int) : unit
System.Collections.Generic.Dictionary(comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : unit
System.Collections.Generic.Dictionary(dictionary: System.Collections.Generic.IDictionary<'TKey,'TValue>) : unit
System.Collections.Generic.Dictionary(capacity: int, comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : unit
System.Collections.Generic.Dictionary(dictionary: System.Collections.Generic.IDictionary<'TKey,'TValue>, comparer: System.Collections.Generic.IEqualityComparer<'TKey>) : unit
System.Collections.Generic.Dictionary.ContainsKey(key: int) : bool
val not : value:bool -> bool
Full name: Microsoft.FSharp.Core.Operators.not
System.Collections.Generic.Dictionary.Add(key: int, value: int) : unit
type MyClass =
static member MyFunction : ?x:int * ?y:int -> int
static member MyFunction2 : [<ParamArray>] rest:int array -> int
Full name: index.MyClass
static member MyClass.MyFunction : ?x:int * ?y:int -> int
Full name: index.MyClass.MyFunction
val x : int option
val y : int option
val defaultArg : arg:'T option -> defaultValue:'T -> 'T
Full name: Microsoft.FSharp.Core.Operators.defaultArg
static member MyClass.MyFunction2 : [<ParamArray>] rest:int array -> int
Full name: index.MyClass.MyFunction2
Multiple items
type ParamArrayAttribute =
inherit Attribute
new : unit -> ParamArrayAttribute
Full name: System.ParamArrayAttribute
--------------------
ParamArrayAttribute() : unit
val rest : int array
type 'T array = 'T []
Full name: Microsoft.FSharp.Core.array<_>
type Array =
member Clone : unit -> obj
member CopyTo : array:Array * index:int -> unit + 1 overload
member GetEnumerator : unit -> IEnumerator
member GetLength : dimension:int -> int
member GetLongLength : dimension:int -> int64
member GetLowerBound : dimension:int -> int
member GetUpperBound : dimension:int -> int
member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
member Initialize : unit -> unit
member IsFixedSize : bool
...
Full name: System.Array
val reduce : reduction:('T -> 'T -> 'T) -> array:'T [] -> 'T
Full name: Microsoft.FSharp.Collections.Array.reduce
static member MyClass.MyFunction : ?x:int * ?y:int -> int
argument y : int option
static member MyClass.MyFunction2 : [<ParamArray>] rest:int array -> int
Multiple items
type AbstractClassAttribute =
inherit Attribute
new : unit -> AbstractClassAttribute
Full name: Microsoft.FSharp.Core.AbstractClassAttribute
--------------------
new : unit -> AbstractClassAttribute
Multiple items
type AbstractBaseClass =
new : unit -> AbstractBaseClass
abstract member Add : int -> int -> int
abstract member Pi : float
override Add : x:int -> y:int -> int
Full name: index.AbstractBaseClass
--------------------
new : unit -> AbstractBaseClass
abstract member AbstractBaseClass.Add : int -> int -> int
Full name: index.AbstractBaseClass.Add
abstract member AbstractBaseClass.Pi : float
Full name: index.AbstractBaseClass.Pi
Multiple items
val float : value:'T -> float (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.float
--------------------
type float = Double
Full name: Microsoft.FSharp.Core.float
--------------------
type float<'Measure> = float
Full name: Microsoft.FSharp.Core.float<_>
val this : AbstractBaseClass
override AbstractBaseClass.Add : x:int -> y:int -> int
Full name: index.AbstractBaseClass.Add
type MyInterface =
interface
abstract member Square : float -> float
end
Full name: index.MyInterface
abstract member MyInterface.Square : float -> float
Full name: index.MyInterface.Square
Multiple items
type StructAttribute =
inherit Attribute
new : unit -> StructAttribute
Full name: Microsoft.FSharp.Core.StructAttribute
--------------------
new : unit -> StructAttribute
Multiple items
type MyStruct =
struct
new : x:float * y:float -> MyStruct
member X : float
member Y : float
end
Full name: index.MyStruct
--------------------
MyStruct()
new : x:float * y:float -> MyStruct
val x : float
val y : float
member MyStruct.X : float
Full name: index.MyStruct.X
val __ : byref<MyStruct>
member MyStruct.Y : float
Full name: index.MyStruct.Y
type Double =
struct
member CompareTo : value:obj -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member ToString : unit -> string + 3 overloads
static val MinValue : float
static val MaxValue : float
static val Epsilon : float
static val NegativeInfinity : float
static val PositiveInfinity : float
...
end
Full name: System.Double
val x : Double
member Double.Square : float
Full name: index.Square
type Math =
static val PI : float
static val E : float
static member Abs : value:sbyte -> sbyte + 6 overloads
static member Acos : d:float -> float
static member Asin : d:float -> float
static member Atan : d:float -> float
static member Atan2 : y:float * x:float -> float
static member BigMul : a:int * b:int -> int64
static member Ceiling : d:decimal -> decimal + 1 overload
static member Cos : d:float -> float
...
Full name: System.Math
Math.Sqrt(d: float) : float
Multiple items
type DerivedClass =
inherit AbstractBaseClass
interface MyInterface
new : param1:int -> DerivedClass
new : param1:int * param2:int -> DerivedClass
override Add : int -> int -> int
member Area : int
member Area2 : int
override Pi : float
member Area : int with set
member Area2 : int with set
...
Full name: index.DerivedClass
--------------------
new : param1:int -> DerivedClass
new : param1:int * param2:int -> DerivedClass
val param1 : int
val param2 : int
val mutable area : int
val this : DerivedClass
override DerivedClass.Add : int -> int -> int
Full name: index.DerivedClass.Add
override DerivedClass.Pi : float
Full name: index.DerivedClass.Pi
member DerivedClass.Area : int with set
Full name: index.DerivedClass.Area
val set : elements:seq<'T> -> Set<'T> (requires comparison)
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.set
val v : int
static member DerivedClass.StaticValue : int
Full name: index.DerivedClass.StaticValue
override DerivedClass.Square : x:float -> float
Full name: index.DerivedClass.Square
val o1 : DerivedClass
Full name: index.o1
val o2 : MyInterface
Full name: index.o2
abstract member MyInterface.Square : float -> float
val o3 : MyInterface
Full name: index.o3
val reverse : x:'a * y:'b * z:'c * u:'d -> 'd * 'c * 'b * 'a
Full name: index.reverse
val x : 'a
val y : 'b
val z : 'c
val u : 'd
val myTuple : int * float * string * int list
Full name: index.myTuple
val li : int list
Full name: index.li
type MyRecord =
{id: int;
qt: float;
name: string;
li: int list;}
Full name: index.MyRecord
MyRecord.id: int
MyRecord.qt: float
MyRecord.name: string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
MyRecord.li: int list
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val myRecord : MyRecord
Full name: index.myRecord
val id : x:'T -> 'T
Full name: Microsoft.FSharp.Core.Operators.id
val id2 : int
Full name: index.id2
val name2 : string
Full name: index.name2
val myRecord2 : MyRecord
Full name: index.myRecord2
type Term =
| Var of string
| Fun of string * Term
| App of Term * Term
Full name: index.Term
union case Term.Var: string -> Term
union case Term.Fun: string * Term -> Term
union case Term.App: Term * Term -> Term
val formatTerm : term:Term -> string
Full name: index.formatTerm
val term : Term
val n : string
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val x : string
val b : Term
val f : Term
type Shape =
| Rectangle of width: float * length: float
| Circle of radius: float
| Prism of width: float * float * height: float
Full name: index.Shape
union case Shape.Rectangle: width: float * length: float -> Shape
union case Shape.Circle: radius: float -> Shape
union case Shape.Prism: width: float * float * height: float -> Shape
val matchShapeList : _arg1:Shape list -> float option
Full name: index.matchShapeList
union case Option.None: Option<'T>
val shape : Shape
val length : float
union case Option.Some: Value: 'T -> Option<'T>
val r : float
val failwith : message:string -> 'T
Full name: Microsoft.FSharp.Core.Operators.failwith
val rest : Shape list
val i : int
active recognizer Even: int -> Choice<unit,unit>
Full name: index.( |Even|Odd| )
active recognizer Odd: int -> Choice<unit,unit>
Full name: index.( |Even|Odd| )
val str : string
type Int32 =
struct
member CompareTo : value:obj -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member ToString : unit -> string + 3 overloads
static val MaxValue : int
static val MinValue : int
static member Parse : s:string -> int + 3 overloads
static member TryParse : s:string * result:int -> bool + 1 overload
end
Full name: System.Int32
Int32.TryParse(s: string, result: byref<int>) : bool
Int32.TryParse(s: string, style: Globalization.NumberStyles, provider: IFormatProvider, result: byref<int>) : bool
Double.TryParse(s: string, result: byref<float>) : bool
Double.TryParse(s: string, style: Globalization.NumberStyles, provider: IFormatProvider, result: byref<float>) : bool
val f : float
active recognizer Integer: string -> int option
Full name: index.( |Integer|_| )
active recognizer Float: string -> float option
Full name: index.( |Float|_| )
namespace System.Text
namespace System.Text.RegularExpressions
val regex : string
Multiple items
type Regex =
new : pattern:string -> Regex + 1 overload
member GetGroupNames : unit -> string[]
member GetGroupNumbers : unit -> int[]
member GroupNameFromNumber : i:int -> string
member GroupNumberFromName : name:string -> int
member IsMatch : input:string -> bool + 1 overload
member Match : input:string -> Match + 2 overloads
member Matches : input:string -> MatchCollection + 1 overload
member Options : RegexOptions
member Replace : input:string * replacement:string -> string + 5 overloads
...
Full name: System.Text.RegularExpressions.Regex
--------------------
Regex(pattern: string) : unit
Regex(pattern: string, options: RegexOptions) : unit
Regex.Match(input: string, pattern: string) : Match
Regex.Match(input: string, pattern: string, options: RegexOptions) : Match
val m : Match
property Group.Success: bool
val x : Group
property Match.Groups: GroupCollection
property Capture.Value: string
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| ( [] )
| ( :: ) of Head: 'T * Tail: 'T list
interface IEnumerable
interface IEnumerable<'T>
member GetSlice : startIndex:int option * endIndex:int option -> 'T list
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
Full name: Microsoft.FSharp.Collections.List<_>
val tail : list:'T list -> 'T list
Full name: Microsoft.FSharp.Collections.List.tail
val parseDate : str:string -> DateTime
Full name: index.parseDate
active recognizer ParseRegex: string -> string -> string list option
Full name: index.( |ParseRegex|_| )
val m : int
val d : int
Multiple items
type DateTime =
struct
new : ticks:int64 -> DateTime + 10 overloads
member Add : value:TimeSpan -> DateTime
member AddDays : value:float -> DateTime
member AddHours : value:float -> DateTime
member AddMilliseconds : value:float -> DateTime
member AddMinutes : value:float -> DateTime
member AddMonths : months:int -> DateTime
member AddSeconds : value:float -> DateTime
member AddTicks : value:int64 -> DateTime
member AddYears : value:int -> DateTime
...
end
Full name: System.DateTime
--------------------
DateTime()
(+0 other overloads)
DateTime(ticks: int64) : unit
(+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int) : unit
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, kind: DateTimeKind) : unit
(+0 other overloads)
val max : x:'a -> y:'a -> 'a (requires comparison)
Full name: index.max
val x : 'a (requires comparison)
val y : 'a (requires comparison)
val makeNoise : animal:'a -> unit (requires member MakeNoise)
Full name: index.makeNoise
val animal : 'a (requires member MakeNoise)
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
Multiple items
type Dog =
new : unit -> Dog
member MakeNoise : unit -> unit
Full name: index.Dog
--------------------
new : unit -> Dog
member Dog.MakeNoise : unit -> unit
Full name: index.Dog.MakeNoise
Multiple items
type Cat =
new : unit -> Cat
member MakeNoise : unit -> unit
Full name: index.Cat
--------------------
new : unit -> Cat
member Cat.MakeNoise : unit -> unit
Full name: index.Cat.MakeNoise
val map : mapping:('T -> 'U) -> list:'T list -> 'U list
Full name: Microsoft.FSharp.Collections.List.map
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []
Full name: Microsoft.FSharp.Collections.Array.map
module Seq
from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
Multiple items
type Random =
new : unit -> Random + 1 overload
member Next : unit -> int + 2 overloads
member NextBytes : buffer:byte[] -> unit
member NextDouble : unit -> float
Full name: System.Random
--------------------
Random() : unit
Random(Seed: int) : unit
val initInfinite : initializer:(int -> 'T) -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.initInfinite
Multiple items
module Map
from Microsoft.FSharp.Collections
--------------------
type Map<'Key,'Value (requires comparison)> =
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
member Add : key:'Key * value:'Value -> Map<'Key,'Value>
member ContainsKey : key:'Key -> bool
override Equals : obj -> bool
member Remove : key:'Key -> Map<'Key,'Value>
...
Full name: Microsoft.FSharp.Collections.Map<_,_>
--------------------
new : elements:seq<'Key * 'Value> -> Map<'Key,'Value>
val box : value:'T -> obj
Full name: Microsoft.FSharp.Core.Operators.box
val unbox : value:obj -> 'T
Full name: Microsoft.FSharp.Core.Operators.unbox
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.filter
val take : count:int -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.take
val sortBy : projection:('T -> 'Key) -> source:seq<'T> -> seq<'T> (requires comparison)
Full name: Microsoft.FSharp.Collections.Seq.sortBy
val toList : source:seq<'T> -> 'T list
Full name: Microsoft.FSharp.Collections.Seq.toList
property DateTime.Now: DateTime
namespace System.Timers
Multiple items
type Timer =
inherit Component
new : unit -> Timer + 1 overload
member AutoReset : bool with get, set
member BeginInit : unit -> unit
member Close : unit -> unit
member Enabled : bool with get, set
member EndInit : unit -> unit
member Interval : float with get, set
member Site : ISite with get, set
member Start : unit -> unit
member Stop : unit -> unit
...
Full name: System.Timers.Timer
--------------------
Timers.Timer() : unit
Timers.Timer(interval: float) : unit
module Observable
from Microsoft.FSharp.Control
val map : mapping:('T -> 'U) -> source:IObservable<'T> -> IObservable<'U>
Full name: Microsoft.FSharp.Control.Observable.map
val merge : source1:IObservable<'T> -> source2:IObservable<'T> -> IObservable<'T>
Full name: Microsoft.FSharp.Control.Observable.merge
val pairwise : source:IObservable<'T> -> IObservable<'T * 'T>
Full name: Microsoft.FSharp.Control.Observable.pairwise
val partition : predicate:('T -> bool) -> source:IObservable<'T> -> IObservable<'T> * IObservable<'T>
Full name: Microsoft.FSharp.Control.Observable.partition
val async : AsyncBuilder
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
namespace System.Net
type WebRequest =
inherit MarshalByRefObject
member Abort : unit -> unit
member AuthenticationLevel : AuthenticationLevel with get, set
member BeginGetRequestStream : callback:AsyncCallback * state:obj -> IAsyncResult
member BeginGetResponse : callback:AsyncCallback * state:obj -> IAsyncResult
member CachePolicy : RequestCachePolicy with get, set
member ConnectionGroupName : string with get, set
member ContentLength : int64 with get, set
member ContentType : string with get, set
member Credentials : ICredentials with get, set
member EndGetRequestStream : asyncResult:IAsyncResult -> Stream
...
Full name: System.Net.WebRequest
Net.WebRequest.Create(requestUri: Uri) : Net.WebRequest
Net.WebRequest.Create(requestUriString: string) : Net.WebRequest
Multiple items
type Uri =
new : uriString:string -> Uri + 5 overloads
member AbsolutePath : string
member AbsoluteUri : string
member Authority : string
member DnsSafeHost : string
member Equals : comparand:obj -> bool
member Fragment : string
member GetComponents : components:UriComponents * format:UriFormat -> string
member GetHashCode : unit -> int
member GetLeftPart : part:UriPartial -> string
...
Full name: System.Uri
--------------------
Uri(uriString: string) : unit
Uri(uriString: string, uriKind: UriKind) : unit
Uri(baseUri: Uri, relativeUri: string) : unit
Uri(baseUri: Uri, relativeUri: Uri) : unit
namespace System.IO
Multiple items
type StreamReader =
inherit TextReader
new : stream:Stream -> StreamReader + 9 overloads
member BaseStream : Stream
member Close : unit -> unit
member CurrentEncoding : Encoding
member DiscardBufferedData : unit -> unit
member EndOfStream : bool
member Peek : unit -> int
member Read : unit -> int + 1 overload
member ReadLine : unit -> string
member ReadToEnd : unit -> string
...
Full name: System.IO.StreamReader
--------------------
IO.StreamReader(stream: IO.Stream) : unit
IO.StreamReader(path: string) : unit
IO.StreamReader(stream: IO.Stream, detectEncodingFromByteOrderMarks: bool) : unit
IO.StreamReader(stream: IO.Stream, encoding: Text.Encoding) : unit
IO.StreamReader(path: string, detectEncodingFromByteOrderMarks: bool) : unit
IO.StreamReader(path: string, encoding: Text.Encoding) : unit
IO.StreamReader(stream: IO.Stream, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool) : unit
IO.StreamReader(path: string, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool) : unit
IO.StreamReader(stream: IO.Stream, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
IO.StreamReader(path: string, encoding: Text.Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task -> Async<unit>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken
Full name: Microsoft.FSharp.Control.Async
--------------------
type Async<'T>
Full name: Microsoft.FSharp.Control.Async<_>
static member Async.Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:Threading.CancellationToken -> 'T
module Option
from Microsoft.FSharp.Core
val bind : binder:('T -> 'U option) -> option:'T option -> 'U option
Full name: Microsoft.FSharp.Core.Option.bind
val query : Linq.QueryBuilder
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
Multiple items
type MeasureAttribute =
inherit Attribute
new : unit -> MeasureAttribute
Full name: Microsoft.FSharp.Core.MeasureAttribute
--------------------
new : unit -> MeasureAttribute
F# for Scala Developers
Walking into the dark side
meets
Scala and
F# Madrid Meetup groups
How much do Scala and F# look alike?
- Bring (non-strict) Functional Programming to Java and .NET
- Full compatibility with their host platforms
- Built-in functional libraries
- Static safety with type inference
- Mostly expression based (side-effects also allowed)
- Open source projects with vibrant communities
How much do Scala and F# differ?
Scala
- Embraces both Object Oriented and Functional Programming
- Designed not to scare OOP developers: curly-brace
- Very powerful and flexible syntax
- Very rich class system
- Language team works separately from Java team
How much do Scala and F# differ?
F#
- Multi-paradigm but functional-first
- Inherited from Ocaml: indentation sensitive
- Less flexible syntax, more focused on consistency
- Three flavors: project (.fs), script (.fsx) and signature (.fsi) files
- Language team works together (more or less) with .NET team
Functional features like generics and tail-call
instructions are native to the platform
Let's see some code examples...
Constants, Variables and null
Scala
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
|
val a = 5 // Type inferred constant declaration
val b: Double = 5.0 // Explicitly typed constant declaration
var c = 5 // Variable declaration
c = 10 // Mutation
class Point(xc: Int, yc: Int) {
val x: Int = xc
val y: Int = yc
}
val p: Point = null // null allowed for custom classes
|
F#
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
|
let a = 5 // Type inferred constant declaration
let b: float = 5. // Explicitly typed constant declaration
let a = 2 // Shadowing
// Verbosity penalty for mutability
let mutable c = 5 // Variable declaration
c <- 10 // Mutation
// Reference cells: used mainly before F# 4.0
// to capture mutable variables in closures
let r = ref 5
printfn "%i" !r // Accessing cell content
r := 2 // Mutating cell content
type Point(x: int, y: int) =
member val X = x
member val Y = y
// Doesn't compile, null not allowed in custom classes
//let p: Point = null
|
Imperative loops
Scala
1:
2:
3:
4:
5:
6:
7:
8:
9:
|
for (index <- 1 to 5) {
println(s"$index times 5 is ${index * 5}")
}
var index = 1
while (index < 6) {
println(s"$index times 5 is ${index * 5}")
index = index + 1
}
|
F#
As in Scala, break and continue are missing from the language.
Recursion or stream functions are preferred.
1:
2:
3:
4:
5:
6:
7:
|
for index = 1 to 5 do
printfn "%i times 5 is %i" index (index * 5)
let mutable index = 1
while index < 6 do
printfn "%i times 5 is %i" index (index * 5)
index <- index + 1
|
Functions
Scala
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
|
def myFunction(x: Int, y: Int) = {
def privateFunction(z: Int) = z * 2
privateFunction(x + y)
}
def curryFunction(x: Int)(y: Int) = x * y
def highOrderFunction(f: Int => Int, y: Int) = f(y)
def recursiveFuncion(x: Int): Int =
if (x == 1) 1 else x * (recursiveFuncion(x - 1))
// Function as object instead of method
val myLambda = (x: Int, y: Int) => x * y
// Lambda shortcut, not possible in F#
val myLambda2: Function2[Int,Int,Int] = _*_
|
Scala
Memoize Pattern
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
|
val memoizeFunction = {
val cache = scala.collection.mutable.HashMap.empty[Int,Int]
(x: Int) => {
if (cache.contains(x) == false) {
println(s"Adding $x to cache...")
cache += (x -> x * 2)
}
cache(x)
}
}
|
F#
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
|
module MyMod =
let myFunction x y = x + y
let myFunction2 x y =
let privateFunction z = z * 2
// let privateFunction = fun z -> z * 2 // Same effect
privateFunction (x + y)
let highOrderFunction f y = f y
let rec recursiveFuncion x =
if x = 1 then x else x * (recursiveFuncion (x - 1))
let memoizeFunction =
let cache = System.Collections.Generic.Dictionary<int, int>()
fun x ->
if cache.ContainsKey x |> not then
cache.Add(x, x * 2)
cache.[x]
|
F#
As seen above, functions in F# are usually contained in modules (curried by default)
Optional and rest parameters are only accepted in non-curried class methods
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
|
open System
type MyClass =
static member MyFunction(?x, ?y) =
(defaultArg x 5) + (defaultArg y 10)
static member MyFunction2([<ParamArray>] rest: int array) =
Array.reduce (+) rest
MyClass.MyFunction(y = 4)
MyClass.MyFunction2(1, 2, 3)
|
Classes
Scala
Classes are very powerful in Scala and different from F#:
- Singleton objects
- Traits and abstract types
- Compound types and mixins
F#
- F# doesn't focus on classes
- Their main purpose is compatibility with .NET Base Class Library
- Mostly same functionality as C# with different Syntax and some additional
features (like primary constructors)
- Interfaces are just abstract classes without default method implementations
- No mixins, only multiple interface implementation is possible
(extension methods are allowed)
- Object Expressions allow dynamic implementation of interfaces
Abstract classes, interfaces and structs (value classes)
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
|
[<AbstractClass>] // If at least one member lacks
type AbstractBaseClass() = // implementation, the class must
abstract member Add: int -> int -> int // be marked as abstract
abstract member Pi: float
default this.Add x y = x + y // Default implementation
type MyInterface = // Interfaces are just abstract
abstract member Square: float -> float // classes without implementations
[<Struct>] // Memory for structs is allocated
type MyStruct(x: float, y: float) = // on the stack, not the heap
member __.X = x // Instances are passed by value,
member __.Y = y // not by reference
type System.Double with // Type extension
member x.Square = System.Math.Sqrt(x)
|
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
|
type DerivedClass(param1, param2) =
inherit AbstractBaseClass() // Inheritance
let mutable area = 0 // Private field
new(param1) = DerivedClass(param1, 5) // Secondary constructor
override this.Add _ _ = param1 + param2
override this.Pi = 3.14 // Getter-only property
member this.Area
with get() = area // Getter-Setter property
and set(v) = area <- v
member val Area2 = 0 with get, set // Auto implemented property
static member StaticValue = 5 // Static members are allowed
interface MyInterface with // Interface implementation
member this.Square x = x * x // (always explicit)
|
Object expressions
1:
2:
3:
4:
5:
6:
7:
8:
9:
|
let o1 = DerivedClass(4) // new keyword is optional
//o1.Square 5. // Cannot access interface methods implicitly
let o2: MyInterface = upcast o1 // Casting is automatic when passing arguments
printfn "%f" (o2.Square 5.)
let o3 = // Object expressions create an anonymous object
{ new MyInterface with // implementing the interface
member __.Square x = x ** 2. }
printfn "%f" (o3.Square 5.)
|
Tuples and Records
In F#, tuples, records (lightweight classes) and discriminated unions (ADT)
are usually preferred, with logic separated in module functions.
Tuples in Scala
1:
2:
3:
4:
5:
|
def reverse(x: Int, y: Double, z: String, u: List[Int]) = (u, z, y, x)
val myTuple = (1, 2., "hola", List(1,2,3))
val (_,_,_,_li) = myTuple // Destructuring
myTuple._4 // Direct access to members
//reverse(myTuple) // Error
|
Tuples in F#
1:
2:
3:
4:
5:
|
let reverse(x, y, z, u) = (u, z, y, x)
let myTuple = 1, 2., "hola", [1;2;3] // Parens can be omitted
let (_,_,_,li) = myTuple // Destructuring
//myTuple._4 // No direct acccess to members but...
reverse myTuple // can be destructured in function args
|
F# Records
Named tuples or lightweight classes, if you must
1:
2:
3:
4:
5:
6:
7:
8:
9:
|
// Beware! In F# commas are only for tuples. Separating statements, members,
// list items, etc. is done with either semicolons or line breaks
type MyRecord = { id: int; qt: float; name: string; li: int list }
let myRecord = { id = 1; qt = 2.; name = "hola"; li = [1;2;3] }
myRecord.id // Member access
let { id = id2; name = name2 } = myRecord // Destructuring
let myRecord2 = { myRecord with qt = 5. } // Copying
|
We can reach a similar effect in Scala marking constructor parameters as fields
1:
2:
|
class MyRecord(val id: Int, val qt: Double,
val name: String, val li: List[Int]) {}
|
Algebraic Data Types and Pattern Matching
Scala
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
|
sealed abstract class Term
case class Var(name: String) extends Term
case class Fun(arg: String, body: Term) extends Term
case class App(f: Term, v: Term) extends Term
def formatTerm(term: Term): String = term match {
case Var(n) => n
case Fun(x, b) => s"^$x.${formatTerm(b)}"
case App(f, v) => s"(${formatTerm(f)} ${formatTerm(v)})"
}
println(formatTerm(Fun("x", Fun("y", App(Var("x"), Var("y"))))))
|
F#
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
|
type Term =
| Var of string
| Fun of string * Term
| App of Term * Term
// Compiler warns you if the matching is not comprehensive
let rec formatTerm term =
match term with
| Var(n) -> sprintf "%s" n
| Fun(x, b) -> sprintf "^%s.%s" x (formatTerm b)
| App(f, b) -> sprintf "(%s %s)" (formatTerm f) (formatTerm b)
// Pipelining is very idiomatic in F#
Fun("x", Fun("y", App(Var("x"), Var("y"))))
|> formatTerm
|> printfn "%s"
|
F# (a more contrived example)
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
|
type Shape =
| Rectangle of width: float * length: float
| Circle of radius: float
| Prism of width: float * float * height: float
let rec matchShapeList = function // Shortcut
| [] -> None // Empty list
| [shape] -> // Single item
match shape with
| Rectangle(length, 10.) -> Some(length) // Constant
| Circle r when r > 5.0 -> Some(r) // Guard
| _ -> failwith "Unknown shape"
| _::rest -> matchShapeList rest // Wildcard
|
Scala Extractor Objects
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
|
object Even {
def unapply(x: Int) =
if (x % 2 == 0) Some(x) else None
}
object Odd {
def unapply(x: Int) =
if (x % 2 == 0) None else Some(x)
}
println(5 match {
case Even(_) => "Hello"
case Odd(_) => "Goodbye"
})
|
F# Exhaustive Active Patterns
1:
2:
3:
4:
5:
|
let (|Even|Odd|) i =
if i % 2 = 0 then Even else Odd
match 5 with Even -> "Hello" | Odd -> "Goodbye"
|> printfn "%s"
|
F# Partial Active Pattern
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
|
let (|Integer|_|) (str: string) =
match System.Int32.TryParse str with
| (true, i) -> Some i | (false, _) -> None
let (|Float|_|) (str: string) =
match System.Double.TryParse str with
| (true, f) -> Some f | (false, _) -> None
match "Hola" with
| Integer i -> printfn "%d : Integer" i
| Float f -> printfn "%f : Floating point" f
// Appease the compiler
| _ as str -> printfn "%s : Not matched" str
|
F# Parameterized Active Patterns
Specializing the pattern by passing extra parameters
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
|
open System.Text.RegularExpressions
let (|ParseRegex|_|) regex str =
match Regex.Match(str, regex) with
| m when not m.Success -> None
| m -> [for x in m.Groups -> x.Value] |> List.tail |> Some
let parseDate str =
match str with
| ParseRegex @"^(\d{1,2})/(\d{1,2})/(\d{1,2})$"
[Integer m; Integer d; Integer y]
-> System.DateTime(y + 2000, m, d)
| ParseRegex @"^(\d{1,2})/(\d{1,2})/(\d{3,4})$"
[Integer m; Integer d; Integer y]
-> System.DateTime(y, m, d)
| ParseRegex @"^(\d{1,4})-(\d{1,2})-(\d{1,2})$"
[Integer y; Integer m; Integer d]
-> System.DateTime(y, m, d)
| _ -> System.DateTime()
|
Kitty Break
Generics
F# generics are very similar to Scala, with a few diferences:
Automatic Generalization
If the function has no dependency on the specific type of a parameter, the type is inferred to be generic
Statically Resolved Type Parameters
Type parameter replaced with actual types at compile time instead of at run time
No generics of generics
Generics are native to .NET platform (no erasures) but on the other hand are more limited (no type classes)
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
|
// Automatic Generalization
let (|>) x f = f x
// val ( |> ) : x:'a -> f:('a -> 'b) -> 'b
// Constraints
let max x y = if x > y then x else y
// val max : x:'a -> y:'a -> 'a when 'a : comparison
// Syntax for statically resolved type parameters is not beautiful
// and it's mainly intented for core library functions. However it
// can be used with inline functions for neat tricks like duck typing
let inline makeNoise (animal: ^a when ^a : (member MakeNoise: unit->unit)) =
(^a: (member MakeNoise: unit->unit) animal)
type Dog() = member __.MakeNoise() = printfn "Guau!"
type Cat() = member __.MakeNoise() = printfn "Miau!"
makeNoise(Dog())
makeNoise(Cat())
|
No generics of generics
Type classes like Functor are not allowed
1:
|
Functor.map : ('a->'b) -> 'T<'a> -> 'T<'b>
|
Instead, _map_ must be implemented for each type (or interface)
1:
2:
3:
|
List.map : ('a->'b) -> list<'a> -> list<'b>
Array.map : ('a->'b) -> array<'a> -> array<'b>
Seq.map : ('a->'b) -> seq<'a> -> seq<'b>
|
Collections
F# built-in functions and operators and focus only on a few collection types:
list |
Yes |
Linked list |
List |
seq |
Yes |
Lazy evaluation |
Iterable/Stream |
array |
No |
Random access |
Array |
map |
Yes |
Indexed access |
Map |
set |
Yes |
Unique items |
Set |
Fluent APIs
Scala
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
|
class Person(val name: String, val age: Int) {}
def selectDataRows() = {
val rnd = scala.util.Random
for (i <- Stream.from(1))
yield Map("name" -> s"Person$i",
"age" -> rnd.nextInt(99))
}
selectDataRows()
.map(row => new Person(row("name").asInstanceOf[String],
row("age").asInstanceOf[Int]))
.filter(_.name.startsWith("P"))
.take(20)
.sortBy(_.age)
.toList
// There're multiple libraries in Scala for collections
// Akka-Streams, Scalaz-Stream...
|
F#
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
|
type Person = { name: string; age: int }
let getDataRows() =
let rnd = System.Random()
Seq.initInfinite (fun i ->
Map [ ("name", sprintf "Person%i" i |> box)
("age", rnd.Next 99 |> box) ])
// It's more idiomatic in F# to use module functions
// and the pipe operator rather than methods
getDataRows()
|> Seq.map (fun row -> { name = unbox row.["name"]
age = unbox row.["age"] })
|> Seq.filter (fun p -> p.name.StartsWith("P"))
|> Seq.take 20
|> Seq.sortBy (fun p -> p.age)
|> Seq.toList
// List and Array modules contain the same functions as Seq
// Of course, pipe operator is possible in SCala too
|
F# Comprehensions
F# allows comprensions similar to those in Haskell or Python
1:
2:
3:
4:
5:
|
let myList = [ for i in 1..100 do yield i*i ]
let myArray = [| for i in 1..100 -> i*i |]
let mySeq = seq { for i in 1..100 -> i*i }
// `->` is a shortcut for `do yield`
|
In Scala we would just use functions
1:
|
List.range(1,101).map(i => i*i)
|
Observables
F# core library also includes support for Functional Reactive Programming
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
|
let makeStream interval =
let t1 = System.DateTime.Now
let timer = new System.Timers.Timer(float interval, AutoReset=true)
timer.Start()
timer.Elapsed
|> Observable.map (fun t2 -> interval, t2.SignalTime - t1)
let simultaneousStream, nonSimultaneousStream =
Observable.merge (makeStream 3000) (makeStream 5000)
|> Observable.pairwise
|> Observable.partition (fun ((_,t1), (_,t2)) ->
(t2 - t1).TotalMilliseconds < 50.)
let fizzStream, buzzStream =
nonSimultaneousStream
|> Observable.map (fun (ev1,_) -> ev1)
|> Observable.partition (fun (id,_) -> id=3000)
|
Scala Comprehensions and F# Computation Expressions
In Scala, any type implementing filterWith, map and flatMap can be
used with for comprehensions. This allows, for example, dealing with async
operations in a monadic way.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
|
val usdQuote = Future { connection.getCurrentValue(USD) }
val chfQuote = Future { connection.getCurrentValue(CHF) }
val purchase = for {
usd <- usdQuote
chf <- chfQuote
if isProfitable(usd, chf)
} yield connection.buy(amount, chf)
purchase onSuccess {
case _ => println("Purchased " + amount + " CHF")
}
|
In F#, this can be done using computation expressions
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
|
// Parallel I/O
let fetchUrlAsync url = async {
let req = System.Net.WebRequest.Create(System.Uri url)
use! resp = req.AsyncGetResponse()
use stream = resp.GetResponseStream()
use reader = new System.IO.StreamReader(stream)
return reader.ReadToEnd()
}
[ "http://fsharp.org/"; "http://www.scala-lang.org/" ]
|> List.map fetchUrlAsync
|> Async.Parallel
|> Async.RunSynchronously
|> printfn "%A"
|
Computation expressions convert language constructs like
let, use, do, for or try in syntactic sugar
for continuation passing style operations
F# core has Asynchronous Workflows built-in
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
|
// Parallel CPU
let rec fib x =
if x <= 2
then 1
else fib(x-1) + fib(x-2)
let fibs =
[ for i in 0..40 -> async { return fib(i) } ]
|> Async.Parallel
|> Async.RunSynchronously
|> printfn "%A"
|
Async<'T> is lazy, it will only start running after
calling Async.Start or Async.RunSynchronously
Custom computation expressions
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
|
type MaybeBuilder() =
member __.Bind(x,f) = Option.bind f x
member __.Return v = Some v
member __.ReturnFrom o = o
let maybe = MaybeBuilder()
let riskyOp x y =
if x + y < 100 then Some(x+y) else None
let execMaybe x = maybe {
let! a = riskyOp x (x+1)
let! b = riskyOp a (a+1)
let! c = riskyOp b (b+1)
let! d = riskyOp c (c+1)
return d
}
execMaybe 5
|
Besides Bind and Return, there are other methods
wich can be implemented by custom computations expressions
like Zero, Yield, Combine, For, While or Try
Query expressions
Query expressions provide support for LINQ in F#
1:
2:
3:
4:
5:
6:
|
query {
for n in db.Student do
join e in db.CourseSelection on
(n.StudentID = e.StudentID)
count
}
|
They express transformations on a data source wich can
be translated to another language, usually SQL
1:
2:
3:
|
SELECT COUNT(*) FROM
Student JOIN CourseSelection
ON Student.StudentID = CourseSelection.StudentID
|
And now for a couple of unique F# features...
Units of Measure
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
|
[<Measure>] type km // Define the measure units
[<Measure>] type mi // as simple types decorated
[<Measure>] type h // with Measure attribute
let speed = 90<km> / 1<h> // Can be combined through
let speed' = 55<mi> / 1<h> // arithmetic operations
let v1, v2, v3 = 3.1<km/h>, 2.7<km/h>, 1.5<mi/h>
let sum = v1 + v2
//let sum' = v1 + v3 // Error: doesn't compile
// Can be used in a generic way
type Vector3D<[<Measure>] 'u> =
{ x: float<'u>; y: float<'u>; z: float<'u> }
|
Measure annotations disappear after compilation and thus they have no performance penalty
(Cannot be retrieved by Reflection though)
Type Providers
Static types generated dynamically
JSON
Want more F#?
These slides were made with FSReveal and no kittens were harmed in the process
And here comes the unasked-for advice!
Remember to focus away and blink regularly when staring at the screen for a long time