| @@ -0,0 +1,3 @@ | |||
| { | |||
| "FSharp.suggestGitignore": false | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| open System.Net | |||
| open System | |||
| open System.IO | |||
| let fetchUrl cb url = | |||
| let req = WebRequest.Create(Uri(url)) | |||
| use resp = req.GetResponse() | |||
| use stream = resp.GetResponseStream() | |||
| use reader = new IO.StreamReader(stream) | |||
| cb reader url | |||
| let myCb (reader:IO.StreamReader) url = | |||
| let html = reader.ReadToEnd() | |||
| let html1000 = html.Substring(0,1000) | |||
| printfn "Downloaded %s. First 1000 is %s" url html1000 | |||
| html | |||
| // let blog = fetchUrl myCb "https://blog.etopiei.com" | |||
| // This could also be written `point free` but I like the explicitness | |||
| let generalPageDownload url = fetchUrl myCb url | |||
| generalPageDownload "https://google.com" | |||
| generalPageDownload "https://etopiei.com" | |||
| @@ -0,0 +1,75 @@ | |||
| let myInt = 5 | |||
| let myFloat = 3.14 | |||
| let myString = "Hello" | |||
| let twoToFive = [2;3;4;5] | |||
| let oneToFive = 1 :: twoToFive // New first element | |||
| let zeroToFive = [0;1] @ twoToFive // Concatenation | |||
| let square x = x * x | |||
| square 3 | |||
| let add x y = x + y | |||
| add 2 3 | |||
| let evens list = | |||
| let isEven x = x % 2 = 0 // Inline function | |||
| List.filter isEven list // Basic libary function | |||
| evens oneToFive | |||
| let sumOfQuaresTo100 = | |||
| List.sum ( List.map square [1..100] ) | |||
| let sumOfSquaresTo100piped = | |||
| [1..100] |> List.map square |> List.sum | |||
| let sumOfSquaresTo100WithFun = | |||
| [1..100] |> List.map (fun x->x*x) |> List.sum // `fun` is like a lambda | |||
| // F# Functions return implicitly | |||
| let simplePatternMatch = | |||
| let x = "a" | |||
| match x with | |||
| | "a" -> printfn "x is a" | |||
| | "b" -> printfn "x is b" | |||
| | _ -> printfn "x is something else" | |||
| let validValue = Some(99) | |||
| let invalidValue = None | |||
| let optionPatternMatch input = | |||
| match input with | |||
| | Some i -> printfn "Input is an int=%d" i // similar to c format strings | |||
| | None -> printfn "Input missing" | |||
| optionPatternMatch validValue | |||
| optionPatternMatch invalidValue | |||
| // Stuff with data types | |||
| let twoTuple = 1,2 | |||
| let threeTuple = "a",2,true | |||
| type Person = {First:string; Last:string} // Record types have named fields | |||
| let person1 = {First="john"; Last="roberts"} | |||
| type Temp = | |||
| | DegreesC of float | |||
| | DegreesF of float | |||
| let temp = DegreesF 98.6 | |||
| type Employee = | |||
| | Worker of Person | |||
| | Manager of Employee list | |||
| let worker = Worker person1 | |||
| // Printing stuff out | |||
| printfn "Printing an int %i, a float %f, a bool %b" 1 2.0 true | |||
| printfn "A string %s, and something generic %A" "hello" [1;2;3;4] | |||
| // You can also print complex types that have been created | |||
| printfn "twoTuple=%A,\nPerson=%A,\nTemp=%A,\nEmployee=%A" | |||
| twoTuple person1 temp worker | |||
| @@ -0,0 +1,34 @@ | |||
| let printInt = printfn "%d" | |||
| let product n = | |||
| let initialValue = 1 | |||
| let action productSoFar x = productSoFar * x | |||
| [1..n] |> List.fold action initialValue | |||
| printInt (product 10) | |||
| let sumOfOdds n = | |||
| let initialValue = 0 | |||
| let action sumSoFar x = if x % 2 = 0 then sumSoFar else sumSoFar + x | |||
| [1..n] |> List.fold action initialValue | |||
| printInt (sumOfOdds 10) | |||
| let alternatingSum n = | |||
| let initialValue = (true, 0) | |||
| let action (isNeg, sumSoFar) x = if isNeg then (false, sumSoFar - x) else (true, sumSoFar + x) | |||
| [1..n] |> List.fold action initialValue |> snd // `snd` means the second in a tuple | |||
| printInt (alternatingSum 100) | |||
| // Now we can factor out the commonality and re-write these functions like so: | |||
| let iterAct ini act n = | |||
| [1..n] |> List.fold act ini | |||
| let product2 = iterAct 1 (fun x y -> x * y) | |||
| printInt (product2 10) | |||
| let sumOfOdds2 = iterAct 0 (fun x y -> if y % 2 = 0 then x else x + y) | |||
| printInt (sumOfOdds2 10) | |||
| @@ -0,0 +1,15 @@ | |||
| let rec quicksort list = | |||
| match list with | |||
| | [] -> [] // Empty list | |||
| | firstEl::tail -> | |||
| let smallerEls = | |||
| tail | |||
| |> List.filter (fun e -> e < firstEl) | |||
| |> quicksort | |||
| let larger = | |||
| tail | |||
| |> List.filter (fun e -> e >= firstEl) | |||
| |> quicksort | |||
| smallerEls @ [firstEl] @ larger | |||
| printfn "%A" (quicksort [1;5;23;18;9;1;3]) | |||
| @@ -0,0 +1,58 @@ | |||
| type IntAndBool = {intPart: int; boolPart: bool } // This is a `product` type. i.e. It is made from other simple types | |||
| let x = {intPart=1; boolPart=false} // This is data of type `IntAndBool` | |||
| type IntOrBool = | |||
| | IntChoice of int | |||
| | BoolChoice of bool // This is a `sum` type, i.e. it is made up of either simple type specified here | |||
| let y = IntChoice 42 | |||
| let z = BoolChoice true | |||
| // We can use types to achieve similar control flows to that of imperative languages. | |||
| // Here is code that is analagous to an if-then-else construct | |||
| let booleanExpression = true | |||
| match booleanExpression with | |||
| | true -> printfn "true" // Do things for true | |||
| | false -> printfn "false" // Do things for false | |||
| // Notice that this is very concise syntax and gets to the core of what we want to do | |||
| // Here's a 'switch' statement | |||
| let aDigit = 3 | |||
| match aDigit with | |||
| | 1 -> printfn "1" // Do things for 1 | |||
| | 2 -> printfn "2" // Do things for 2 | |||
| | _ -> printfn "Something else" // like 'default' in switch | |||
| // For loops are replaced with recursion | |||
| let aList = [1;2;3] | |||
| let rec printList list = | |||
| match list with | |||
| | [] -> [] // Empty | |||
| | head::tail -> // Process first element, then recurse | |||
| printfn "%d" head | |||
| printList tail | |||
| printList aList | |||
| // To do something like polymorphism | |||
| // we create `sum types` | |||
| type Shape = | |||
| | Circle of radius:int | |||
| | Rectangle of height:int * width:int // Note tuples defined with '*' | |||
| | Point of x:int * y:int | |||
| | Polygon of pointList:(int * int) list | |||
| let draw shape = | |||
| match shape with | |||
| | Circle radius -> printfn "The circle has radius: %d" radius | |||
| | Rectangle (height, width) -> printfn "Height is %d" height // etc.. | |||
| | Polygon points -> points |> List.iter (printfn "%A") // you get it | |||
| | _ -> printfn "I'm done" | |||
| // Then you can do things with lists like: | |||
| // shapes |> List.iter draw (imagine shapes is a list of shapes) | |||