1
0
mirror of https://github.com/adambard/learnxinyminutes-docs.git synced 2025-09-25 13:58:59 +02:00

removing whitespace all over

This commit is contained in:
Gabriel Halley
2015-10-07 23:11:24 -04:00
parent a793d16e37
commit 960ee4a185
39 changed files with 679 additions and 679 deletions

View File

@@ -5,7 +5,7 @@ contributors:
filename: learnfsharp.fs
---
F# is a general purpose functional/OO programming language. It's free and open source, and runs on Linux, Mac, Windows and more.
F# is a general purpose functional/OO programming language. It's free and open source, and runs on Linux, Mac, Windows and more.
It has a powerful type system that traps many errors at compile time, but it uses type inference so that it reads more like a dynamic language.
@@ -90,7 +90,7 @@ let simplePatternMatch =
| _ -> printfn "x is something else" // underscore matches anything
// F# doesn't allow nulls by default -- you must use an Option type
// and then pattern match.
// and then pattern match.
// Some(..) and None are roughly analogous to Nullable wrappers
let validValue = Some(99)
let invalidValue = None
@@ -115,7 +115,7 @@ printfn "A string %s, and something generic %A" "hello" [1;2;3;4]
// into a string, similar to String.Format in C#.
// ================================================
// More on functions
// More on functions
// ================================================
// F# is a true functional language -- functions are first
@@ -124,30 +124,30 @@ printfn "A string %s, and something generic %A" "hello" [1;2;3;4]
// Modules are used to group functions together
// Indentation is needed for each nested module.
module FunctionExamples =
module FunctionExamples =
// define a simple adding function
let add x y = x + y
// basic usage of a function
let a = add 1 2
printfn "1+2 = %i" a
// partial application to "bake in" parameters
let add42 = add 42
let b = add42 1
printfn "42+1 = %i" b
// composition to combine functions
let add1 = add 1
let add2 = add 2
let add3 = add1 >> add2
let c = add3 7
printfn "3+7 = %i" c
// higher order functions
[1..10] |> List.map add3 |> printfn "new list is %A"
// lists of functions, and more
let add6 = [add1; add2; add3] |> List.reduce (>>)
let d = add6 7
@@ -158,54 +158,54 @@ module FunctionExamples =
// ================================================
// There are three types of ordered collection:
// * Lists are most basic immutable collection.
// * Arrays are mutable and more efficient when needed.
// * Sequences are lazy and infinite (e.g. an enumerator).
// * Lists are most basic immutable collection.
// * Arrays are mutable and more efficient when needed.
// * Sequences are lazy and infinite (e.g. an enumerator).
//
// Other collections include immutable maps and sets
// plus all the standard .NET collections
module ListExamples =
module ListExamples =
// lists use square brackets
// lists use square brackets
let list1 = ["a";"b"]
let list2 = "c" :: list1 // :: is prepending
let list3 = list1 @ list2 // @ is concat
// list comprehensions (aka generators)
let squares = [for i in 1..10 do yield i*i]
let squares = [for i in 1..10 do yield i*i]
// prime number generator
let rec sieve = function
| (p::xs) -> p :: sieve [ for x in xs do if x % p > 0 then yield x ]
| [] -> []
let primes = sieve [2..50]
printfn "%A" primes
printfn "%A" primes
// pattern matching for lists
let listMatcher aList =
let listMatcher aList =
match aList with
| [] -> printfn "the list is empty"
| [first] -> printfn "the list has one element %A " first
| [first; second] -> printfn "list is %A and %A" first second
| _ -> printfn "the list has more than two elements"
| [] -> printfn "the list is empty"
| [first] -> printfn "the list has one element %A " first
| [first; second] -> printfn "list is %A and %A" first second
| _ -> printfn "the list has more than two elements"
listMatcher [1;2;3;4]
listMatcher [1;2]
listMatcher [1]
listMatcher []
listMatcher []
// recursion using lists
let rec sum aList =
let rec sum aList =
match aList with
| [] -> 0
| x::xs -> x + sum xs
sum [1..10]
// -----------------------------------------
// Standard library functions
// -----------------------------------------
// Standard library functions
// -----------------------------------------
// map
let add3 x = x + 3
[1..10] |> List.map add3
@@ -213,68 +213,68 @@ module ListExamples =
// filter
let even x = x % 2 = 0
[1..10] |> List.filter even
// many more -- see documentation
module ArrayExamples =
module ArrayExamples =
// arrays use square brackets with bar
let array1 = [| "a";"b" |]
let first = array1.[0] // indexed access using dot
// pattern matching for arrays is same as for lists
let arrayMatcher aList =
let arrayMatcher aList =
match aList with
| [| |] -> printfn "the array is empty"
| [| first |] -> printfn "the array has one element %A " first
| [| first; second |] -> printfn "array is %A and %A" first second
| _ -> printfn "the array has more than two elements"
| [| |] -> printfn "the array is empty"
| [| first |] -> printfn "the array has one element %A " first
| [| first; second |] -> printfn "array is %A and %A" first second
| _ -> printfn "the array has more than two elements"
arrayMatcher [| 1;2;3;4 |]
// Standard library functions just as for List
[| 1..10 |]
[| 1..10 |]
|> Array.map (fun i -> i+3)
|> Array.filter (fun i -> i%2 = 0)
|> Array.iter (printfn "value is %i. ")
module SequenceExamples =
module SequenceExamples =
// sequences use curly braces
let seq1 = seq { yield "a"; yield "b" }
// sequences can use yield and
// sequences can use yield and
// can contain subsequences
let strange = seq {
// "yield! adds one element
yield 1; yield 2;
// "yield!" adds a whole subsequence
yield! [5..10]
yield! [5..10]
yield! seq {
for i in 1..10 do
for i in 1..10 do
if i%2 = 0 then yield i }}
// test
strange |> Seq.toList
// test
strange |> Seq.toList
// Sequences can be created using "unfold"
// Here's the fibonacci series
let fib = Seq.unfold (fun (fst,snd) ->
Some(fst + snd, (snd, fst + snd))) (0,1)
// test
// test
let fib10 = fib |> Seq.take 10 |> Seq.toList
printf "first 10 fibs are %A" fib10
printf "first 10 fibs are %A" fib10
// ================================================
// Data Types
// Data Types
// ================================================
module DataTypeExamples =
module DataTypeExamples =
// All data is immutable by default
@@ -282,33 +282,33 @@ module DataTypeExamples =
// -- Use a comma to create a tuple
let twoTuple = 1,2
let threeTuple = "a",2,true
// Pattern match to unpack
let x,y = twoTuple //sets x=1 y=2
// ------------------------------------
// Record types have named fields
// ------------------------------------
// ------------------------------------
// Record types have named fields
// ------------------------------------
// Use "type" with curly braces to define a record type
type Person = {First:string; Last:string}
// Use "let" with curly braces to create a record
// Use "let" with curly braces to create a record
let person1 = {First="John"; Last="Doe"}
// Pattern match to unpack
let {First=first} = person1 //sets first="john"
// ------------------------------------
// ------------------------------------
// Union types (aka variants) have a set of choices
// Only case can be valid at a time.
// ------------------------------------
// ------------------------------------
// Use "type" with bar/pipe to define a union type
type Temp =
type Temp =
| DegreesC of float
| DegreesF of float
// Use one of the cases to create one
let temp1 = DegreesF 98.6
let temp2 = DegreesC 37.0
@@ -317,29 +317,29 @@ module DataTypeExamples =
let printTemp = function
| DegreesC t -> printfn "%f degC" t
| DegreesF t -> printfn "%f degF" t
printTemp temp1
printTemp temp1
printTemp temp2
// ------------------------------------
// ------------------------------------
// Recursive types
// ------------------------------------
// ------------------------------------
// Types can be combined recursively in complex ways
// Types can be combined recursively in complex ways
// without having to create subclasses
type Employee =
type Employee =
| Worker of Person
| Manager of Employee list
let jdoe = {First="John";Last="Doe"}
let worker = Worker jdoe
// ------------------------------------
// ------------------------------------
// Modelling with types
// ------------------------------------
// ------------------------------------
// Union types are great for modelling state without using flags
type EmailAddress =
type EmailAddress =
| ValidEmailAddress of string
| InvalidEmailAddress of string
@@ -350,40 +350,40 @@ module DataTypeExamples =
// The combination of union types and record types together
// provide a great foundation for domain driven design.
// You can create hundreds of little types that accurately
// You can create hundreds of little types that accurately
// reflect the domain.
type CartItem = { ProductCode: string; Qty: int }
type Payment = Payment of float
type ActiveCartData = { UnpaidItems: CartItem list }
type PaidCartData = { PaidItems: CartItem list; Payment: Payment}
type ShoppingCart =
type ShoppingCart =
| EmptyCart // no data
| ActiveCart of ActiveCartData
| PaidCart of PaidCartData
| PaidCart of PaidCartData
// ------------------------------------
// ------------------------------------
// Built in behavior for types
// ------------------------------------
// ------------------------------------
// Core types have useful "out-of-the-box" behavior, no coding needed.
// * Immutability
// * Pretty printing when debugging
// * Equality and comparison
// * Serialization
// Pretty printing using %A
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A"
printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A"
twoTuple person1 temp1 worker
// Equality and comparison built in.
// Here's an example with cards.
type Suit = Club | Diamond | Spade | Heart
type Rank = Two | Three | Four | Five | Six | Seven | Eight
| Nine | Ten | Jack | Queen | King | Ace
type Rank = Two | Three | Four | Five | Six | Seven | Eight
| Nine | Ten | Jack | Queen | King | Ace
let hand = [ Club,Ace; Heart,Three; Heart,Ace;
let hand = [ Club,Ace; Heart,Three; Heart,Ace;
Spade,Jack; Diamond,Two; Diamond,Ace ]
// sorting
@@ -391,27 +391,27 @@ module DataTypeExamples =
List.max hand |> printfn "high card is %A"
List.min hand |> printfn "low card is %A"
// ================================================
// Active patterns
// ================================================
module ActivePatternExamples =
module ActivePatternExamples =
// F# has a special type of pattern matching called "active patterns"
// where the pattern can be parsed or detected dynamically.
// F# has a special type of pattern matching called "active patterns"
// where the pattern can be parsed or detected dynamically.
// "banana clips" are the syntax for active patterns
// for example, define an "active" pattern to match character types...
let (|Digit|Letter|Whitespace|Other|) ch =
let (|Digit|Letter|Whitespace|Other|) ch =
if System.Char.IsDigit(ch) then Digit
else if System.Char.IsLetter(ch) then Letter
else if System.Char.IsWhiteSpace(ch) then Whitespace
else Other
else Other
// ... and then use it to make parsing logic much clearer
let printChar ch =
let printChar ch =
match ch with
| Digit -> printfn "%c is a Digit" ch
| Letter -> printfn "%c is a Letter" ch
@@ -424,52 +424,52 @@ module ActivePatternExamples =
// -----------------------------------
// FizzBuzz using active patterns
// -----------------------------------
// You can create partial matching patterns as well
// Just use undercore in the defintion, and return Some if matched.
let (|MultOf3|_|) i = if i % 3 = 0 then Some MultOf3 else None
let (|MultOf5|_|) i = if i % 5 = 0 then Some MultOf5 else None
// the main function
let fizzBuzz i =
let fizzBuzz i =
match i with
| MultOf3 & MultOf5 -> printf "FizzBuzz, "
| MultOf3 -> printf "Fizz, "
| MultOf5 -> printf "Buzz, "
| MultOf3 & MultOf5 -> printf "FizzBuzz, "
| MultOf3 -> printf "Fizz, "
| MultOf5 -> printf "Buzz, "
| _ -> printf "%i, " i
// test
[1..20] |> List.iter fizzBuzz
[1..20] |> List.iter fizzBuzz
// ================================================
// Conciseness
// Conciseness
// ================================================
module AlgorithmExamples =
module AlgorithmExamples =
// F# has a high signal/noise ratio, so code reads
// F# has a high signal/noise ratio, so code reads
// almost like the actual algorithm
// ------ Example: define sumOfSquares function ------
let sumOfSquares n =
let sumOfSquares n =
[1..n] // 1) take all the numbers from 1 to n
|> List.map square // 2) square each one
|> List.sum // 3) sum the results
// test
sumOfSquares 100 |> printfn "Sum of squares = %A"
// ------ Example: define a sort function ------
// test
sumOfSquares 100 |> printfn "Sum of squares = %A"
// ------ Example: define a sort function ------
let rec sort list =
match list with
// If the list is empty
| [] ->
// If the list is empty
| [] ->
[] // return an empty list
// If the list is not empty
| firstElem::otherElements -> // take the first element
let smallerElements = // extract the smaller elements
// If the list is not empty
| firstElem::otherElements -> // take the first element
let smallerElements = // extract the smaller elements
otherElements // from the remaining ones
|> List.filter (fun e -> e < firstElem)
|> List.filter (fun e -> e < firstElem)
|> sort // and sort them
let largerElements = // extract the larger ones
otherElements // from the remaining ones
@@ -479,13 +479,13 @@ module AlgorithmExamples =
List.concat [smallerElements; [firstElem]; largerElements]
// test
sort [1;5;23;18;9;1;3] |> printfn "Sorted = %A"
sort [1;5;23;18;9;1;3] |> printfn "Sorted = %A"
// ================================================
// Asynchronous Code
// ================================================
module AsyncExample =
module AsyncExample =
// F# has built-in features to help with async code
// without encountering the "pyramid of doom"
@@ -495,23 +495,23 @@ module AsyncExample =
open System.Net
open System
open System.IO
open Microsoft.FSharp.Control.CommonExtensions
open Microsoft.FSharp.Control.CommonExtensions
// Fetch the contents of a URL asynchronously
let fetchUrlAsync url =
async { // "async" keyword and curly braces
let fetchUrlAsync url =
async { // "async" keyword and curly braces
// creates an "async" object
let req = WebRequest.Create(Uri(url))
use! resp = req.AsyncGetResponse()
let req = WebRequest.Create(Uri(url))
use! resp = req.AsyncGetResponse()
// use! is async assignment
use stream = resp.GetResponseStream()
use stream = resp.GetResponseStream()
// "use" triggers automatic close()
// on resource at end of scope
use reader = new IO.StreamReader(stream)
let html = reader.ReadToEnd()
printfn "finished downloading %s" url
use reader = new IO.StreamReader(stream)
let html = reader.ReadToEnd()
printfn "finished downloading %s" url
}
// a list of sites to fetch
let sites = ["http://www.bing.com";
"http://www.google.com";
@@ -520,7 +520,7 @@ module AsyncExample =
"http://www.yahoo.com"]
// do it
sites
sites
|> List.map fetchUrlAsync // make a list of async tasks
|> Async.Parallel // set up the tasks to run in parallel
|> Async.RunSynchronously // start them off
@@ -529,58 +529,58 @@ module AsyncExample =
// .NET compatability
// ================================================
module NetCompatibilityExamples =
module NetCompatibilityExamples =
// F# can do almost everything C# can do, and it integrates
// seamlessly with .NET or Mono libraries.
// ------- work with existing library functions -------
let (i1success,i1) = System.Int32.TryParse("123");
if i1success then printfn "parsed as %i" i1 else printfn "parse failed"
// ------- Implement interfaces on the fly! -------
// create a new object that implements IDisposable
let makeResource name =
{ new System.IDisposable
let makeResource name =
{ new System.IDisposable
with member this.Dispose() = printfn "%s disposed" name }
let useAndDisposeResources =
let useAndDisposeResources =
use r1 = makeResource "first resource"
printfn "using first resource"
printfn "using first resource"
for i in [1..3] do
let resourceName = sprintf "\tinner resource %d" i
use temp = makeResource resourceName
printfn "\tdo something with %s" resourceName
use temp = makeResource resourceName
printfn "\tdo something with %s" resourceName
use r2 = makeResource "second resource"
printfn "using second resource"
printfn "done."
printfn "using second resource"
printfn "done."
// ------- Object oriented code -------
// F# is also a fully fledged OO language.
// It supports classes, inheritance, virtual methods, etc.
// interface with generic type
type IEnumerator<'a> =
type IEnumerator<'a> =
abstract member Current : 'a
abstract MoveNext : unit -> bool
abstract MoveNext : unit -> bool
// abstract base class with virtual methods
[<AbstractClass>]
type Shape() =
type Shape() =
//readonly properties
abstract member Width : int with get
abstract member Height : int with get
//non-virtual method
member this.BoundingArea = this.Height * this.Width
//virtual method with base implementation
abstract member Print : unit -> unit
abstract member Print : unit -> unit
default this.Print () = printfn "I'm a shape"
// concrete class that inherits from base class and overrides
type Rectangle(x:int, y:int) =
// concrete class that inherits from base class and overrides
type Rectangle(x:int, y:int) =
inherit Shape()
override this.Width = x
override this.Height = y
@@ -590,20 +590,20 @@ module NetCompatibilityExamples =
let r = Rectangle(2,3)
printfn "The width is %i" r.Width
printfn "The area is %i" r.BoundingArea
r.Print()
r.Print()
// ------- extension methods -------
//Just as in C#, F# can extend existing classes with extension methods.
type System.String with
member this.StartsWithA = this.StartsWith "A"
//test
let s = "Alice"
printfn "'%s' starts with an 'A' = %A" s s.StartsWithA
printfn "'%s' starts with an 'A' = %A" s s.StartsWithA
// ------- events -------
type MyButton() =
let clickEvent = new Event<_>()
@@ -615,11 +615,11 @@ module NetCompatibilityExamples =
// test
let myButton = new MyButton()
myButton.OnClick.Add(fun (sender, arg) ->
myButton.OnClick.Add(fun (sender, arg) ->
printfn "Click event with arg=%O" arg)
myButton.TestEvent("Hello World!")
```
## More Information