@@ -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) |