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 a : obj
Full name: Index.Casting.a
val b : int
Full name: Index.Casting.b
val x2 : obj
Full name: Index.Casting.x2
val x : obj
Full name: Index.Casting2.x
val box : value:'T -> obj
Full name: Microsoft.FSharp.Core.Operators.box
val result : string
Full name: Index.Casting2.result
val a : int
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val x : obj
Full name: Index.Casting3.x
Multiple items val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
-------------------- type string = String
Full name: Microsoft.FSharp.Core.string
val str : string
property String.Length: int
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val x : obj
val x : int
Full name: Index.FExamples.x
val z : unit -> unit
Full name: Index.FExamples.z
val y : unit -> int
Full name: Index.FExamples.y
val f : x:int -> unit
Full name: Index.FExamples.f
val f2 : x:int -> unit
Full name: Index.FExamples.f2
Multiple items type HelloClass = new : unit -> HelloClass member Foo : unit -> string member Y : int member Z : string member Y : int with set static member Bar : unit -> unit
Full name: Index.HelloClass
-------------------- new : unit -> HelloClass
val x : string
val this : HelloClass
member HelloClass.Foo : unit -> string
Full name: Index.HelloClass.Foo
member HelloClass.Z : string
Full name: Index.HelloClass.Z
member HelloClass.Y : int
Full name: Index.HelloClass.Y
val set : elements:seq<'T> -> Set<'T> (requires comparison)
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.set
static member HelloClass.Bar : unit -> unit
Full name: Index.HelloClass.Bar
Multiple items type Foo = new : unit -> Foo
Full name: Index.Foo
-------------------- new : unit -> Foo
type IAmAnInterface = interface abstract member Bark : unit -> string abstract member Bar : string abstract member Foo : string abstract member Bar : string with set end
Full name: Index.IAmAnInterface
abstract member IAmAnInterface.Bark : unit -> string
Full name: Index.IAmAnInterface.Bark
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
Multiple items abstract member IAmAnInterface.Foo : string
Full name: Index.IAmAnInterface.Foo
-------------------- type Foo = new : unit -> Foo
Full name: Index.Foo
-------------------- new : unit -> Foo
abstract member IAmAnInterface.Bar : string with set
Full name: Index.IAmAnInterface.Bar
Multiple items type ClassImplements = interface IAmAnInterface new : unit -> ClassImplements member Bark : unit -> string member Bar : string member Foo : string member Foo2 : string member Bar : string with set
Full name: Index.ClassImplements
-------------------- new : unit -> ClassImplements
val this : ClassImplements
member ClassImplements.Bark : unit -> string
Full name: Index.ClassImplements.Bark
Multiple items member ClassImplements.Foo : string
type Employee = {Name: string; EmployeeId: Guid; Salary: decimal;}
Full name: Index.Employee
Employee.Name: string
Employee.EmployeeId: Guid
Multiple items type Guid = struct new : b:byte[] -> Guid + 4 overloads member CompareTo : value:obj -> int + 1 overload member Equals : o:obj -> bool + 1 overload member GetHashCode : unit -> int member ToByteArray : unit -> byte[] member ToString : unit -> string + 2 overloads static val Empty : Guid static member NewGuid : unit -> Guid static member Parse : input:string -> Guid static member ParseExact : input:string * format:string -> Guid ... end
Multiple items val decimal : value:'T -> decimal (requires member op_Explicit)
Full name: Microsoft.FSharp.Core.Operators.decimal
-------------------- type decimal = Decimal
Full name: Microsoft.FSharp.Core.decimal
-------------------- type decimal<'Measure> = decimal
Full name: Microsoft.FSharp.Core.decimal<_>
val e : Employee
Full name: Index.e
Guid.NewGuid() : Guid
val e2 : Employee
Full name: Index.e2
val a : Collections.Generic.List<int>
Full name: Index.SequenceExamples.a
namespace System.Collections
namespace System.Collections.Generic
Multiple items type List<'T> = new : unit -> List<'T> + 2 overloads member Add : item:'T -> unit member AddRange : collection:IEnumerable<'T> -> unit member AsReadOnly : unit -> ReadOnlyCollection<'T> member BinarySearch : item:'T -> int + 2 overloads member Capacity : int with get, set member Clear : unit -> unit member Contains : item:'T -> bool member ConvertAll<'TOutput> : converter:Converter<'T, 'TOutput> -> List<'TOutput> member CopyTo : array:'T[] -> unit + 2 overloads ... nested type Enumerator
Full name: System.Collections.Generic.List<_>
-------------------- Collections.Generic.List() : unit Collections.Generic.List(capacity: int) : unit Collections.Generic.List(collection: Collections.Generic.IEnumerable<'T>) : unit
val b : Collections.Generic.List<int>
Full name: Index.SequenceExamples.b
type ResizeArray<'T> = Collections.Generic.List<'T>
Full name: Microsoft.FSharp.Collections.ResizeArray<_>
val literalArray : 'a []
Full name: Index.SequenceExamples.literalArray
val arrayOf1To10 : int []
Full name: Index.SequenceExamples.arrayOf1To10
val listOf1To10 : int list
Full name: Index.SequenceExamples.listOf1To10
val literalList : 'a list
Full name: Index.SequenceExamples.literalList
val items : int list
Full name: Index.NotLinq.items
val doubled : seq<int>
Full name: Index.NotLinq.doubled
module Seq
from Microsoft.FSharp.Collections
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
val evens : items:seq<int> -> seq<int>
Full name: Index.NotLinq.evens
val items : seq<int>
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.filter
val items : int list
Full name: Index.Querying.items
val q : seq<int * int>
Full name: Index.Querying.q
val query : Linq.QueryBuilder
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.query
val i : int
custom operation: join var in collection on (outerKey = innerKey). Note that parentheses are required after 'on'
Calls Linq.QueryBuilder.Join
val j : int
custom operation: select ('Result)
Calls Linq.QueryBuilder.Select
Multiple items type MeasureAttribute = inherit Attribute new : unit -> MeasureAttribute
Full name: Microsoft.FSharp.Core.MeasureAttribute
-------------------- new : unit -> MeasureAttribute
openSystemmoduleSyntax=leta=5// var a = 5;letc=1+a// var c = 1 + a;// public int Twice(int x) => x * 2;// the () are optionallettwice(x) =2*x// the () are optionalletd=twice(a)
fsreveal magic c and d are evaluated for you
6
10
Assignment
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
moduleAssignment=// let is a binding not an assignment// = is a binding or comparison not an Assignmentletx=5// not mutableletmutabley=5// parens are just to help visualize it for new learnersletz= (5=6)
// same as above since x is immutable and is 5letz2= (x=6)
y<-y+1
Assignment.z evaluates to
false
Flow Control
if
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
// string F1(int x) => x < 5 ? "<" : ">=";letf1x=ifx<5then"<"else">="// string F2(int lower, int x, int upper) =>// x < lower ? "less than" : x > upper ? "greater than" : "between";letf2lowerxupper=ifx<lowerthen"less than"elseifx>upperthen// or elsif"greater than"else"between"
moduleCasting=letx=5// var x = 5;// var y = (obj) x;// upcast (always succeeds if it compiles)lety=x:>obj// downcast (? mark notes the possibility of failure)// var z = (int)y;letz=y:?>int// var a = (obj)x;leta:obj=upcastx// when the type is inferrable// var b = (int)y;// when the type is inferrable (still could fail)letb:int=downcasty// var x2 = (object)2;letx2:obj=upcast2
moduleCasting2=// box is shorthand for upcast to object// var x = (object) 1;letx:obj=box1// in C#5(maybe even 6) you can't conditionally define a variable// var a2 = x as int?;// due to the line above now a2 is in scope for the rest of the method// x gives a warning here, we haven't covered all possibilities// nothing like that in C# besides default case requirement of switchesletresult=matchxwith// advanced/arguably misusable power:// in F# we don't need to use a separate variable name for the casted variable// if(a2 != null) Console.WriteLine("int value:" + a2);
| :?intasa->sprintf"int value: %i"a// calls ToString if it is not null, a tuple, record or union// if(a1 == null) Console.WriteLine("non-int null value is "+a1);
| null->sprintf"non-int null value is %A"x// prints <null> for null values
"int value: 1"
Casting 3
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
moduleCasting3=// var x = (object)"1";letx:obj=box"1"// conditional matchesmatchxwith// var a3 = x as string; if(a3 != null && a3.Length > 0) ...
| :?stringasstrwhenstr.Length>0->printfn"string value: %s"str// if(a3 == null && x != null) ...// also prints <null> for null values
| x->printfn"value is %O"x// calls toString if it is not null
Syntax 2
fields vs methods
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
// public static class FExamplesmoduleFExamples=// readonly static int x = 1;letx=1letz () = () // void Z() {}lety () =1// int Y() { return 1;}// void F(int x) {}letf (x:int) = () // method// void F2(int x) => F(x);letf2x=fx// method
typeClassImplements () =letx="hello"memberthis.Bark() =x// Foo is a property! not a fieldmemberthis.Foo=x// you can use whatever name you like for `this`member__.Foo2withget() =x// this creates a backing field of its own, using x's value as the initial valuemembervalBar=xwithget,set// f# downside no implicit interface implementation// interface members are always considered explicity implemented// members only show up/compile if you cast the type to the interface firstinterfaceIAmAnInterfacewithmember__.Foo=x// this isn't recursivememberthis.Bark () =this.Bark()
memberthis.Barwithget() =this.Barandsetvalue=this.Bar<-value
typeEmployee= {Name:string; EmployeeId:Guid; Salary:decimal}
lete= {Name="Brandon D'Imperio"; EmployeeId=Guid.NewGuid(); Salary=15.5m}
// how much typing would you need to do in C# to do this?// create a new employee with the same salary// and any other properties that we don't set get copied.lete2= {ewithName="John Doe"; EmployeeId=Guid.NewGuid()}
Collections
Sequences
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
moduleSequenceExamples=// new is not required in F#// you will get a warning on IDisposablesleta=System.Collections.Generic.List<int>()
// same as the line above (using built-in f# aliases)letb=ResizeArray<int>()
letliteralArray= [| |] // also Array.empty// var arrayOf1To10 = Enumerable.Range(1, 10).ToArray();letarrayOf1To10= [| 1..10 |]
// F# list typeletlistOf1To10= [ 1..10 ]
// Microsoft.FSharp.Collections.ListModule.Empty<int>()letliteralList= [] // F# version is immutable
C#
1: 2: 3: 4:
var items =new []{123,456,10,999,9};
var q= from i in items
join j in items on i equals j
selectnew {i,j};
Linq
1: 2: 3: 4: 5: 6: 7: 8: 9:
moduleNotLinq=// var items new [] {123, 456,10,999,9};letitems= [123;456;10;999;9]
// var doubled = items.Select(x => x * 2);letdoubled=items|>Seq.map (funx->x*2)
// this is why C# can't have nice things. look how long this is.// public IEnumerable<int> Evens(IEnumerable<int> items) =>// items.Where(x => x % 2 == 0);letevensitems=items|>Seq.filter (funx->x%2=0)
[<Measure>] typeinch
[<Measure>] typefoot
[<Measure>] typesqft=foot*foot
[<Measure>] typedollarletsizes= [|1700<sqft>;2100<sqft>;1900<sqft>;1300<sqft>|]
letprices= [|53000<dollar>;44000<dollar>;59000<dollar>;82000<dollar>|]
letinchesPerFoot=12<inch/foot>// can't seem to get this working here, nor in linqpad// let numLiteral = 12_000<dollar>
prices.[0]/sizes.[0]
31
Not Covered, barely scratched surface, or not covered well
Good
Pattern matching (exhaustive matching and compiler warnings)
Option types
Units of measure conversions
Discriminated Unions (also recursive DUs)
Tuples (easier and more useful)
Object expressions (we don't need a class or record to implement an interface)
Computation expressions
keywords - rec, function, async, lazy, _
Tupled vs curried method forms
Statically resolved type parameters (structural typing)
Unwanted features (don't have, and don't want) - implicit casts