|
| 1 | +# Functional Quick Start |
| 2 | + |
| 3 | +## Function as Primitive |
| 4 | + |
| 5 | +## Type Composition |
| 6 | + |
| 7 | +The shape of type and behaviors are isolated. |
| 8 | +Functions as first-class citizens, **they don't belong to any type but modules.** |
| 9 | + |
| 10 | +```fsharp |
| 11 | +type Point = { X: float; Y: float } |
| 12 | +
|
| 13 | +module Point = |
| 14 | + let distance p1 p2 = |
| 15 | + sqrt ((p2.X - p1.X) ** 2.0 + (p2.Y - p1.Y) ** 2.0) |
| 16 | +
|
| 17 | + let translate dx dy point = |
| 18 | + { point with |
| 19 | + X = point.X + dx |
| 20 | + Y = point.Y + dy } |
| 21 | +
|
| 22 | +let p1 = { X = 1.0; Y = 2.0 } |
| 23 | +let p2 = Point.translate 3.0 4.0 p1 |
| 24 | +``` |
| 25 | + |
| 26 | +<!-- TODO: add example to show type composition --> |
| 27 | +<!-- TODO: add description about function as objective and value as subjective --> |
| 28 | + |
| 29 | +## Hindley-Milner Type System |
| 30 | + |
| 31 | +```fsharp |
| 32 | +let add a b = a + b |
| 33 | +let foo = add 1 2 // inferred as int -> int -> int |
| 34 | +let bar = add 1.0 2,0 // can't infer // [!code error] |
| 35 | +``` |
| 36 | + |
| 37 | +<!-- TODO: add more appropriate example --> |
| 38 | + |
| 39 | +## Immutable Value |
| 40 | + |
| 41 | +Values are immutable since constructed by default. |
| 42 | + |
| 43 | +```fsharp |
| 44 | +let p1 = { X = 1.0; Y = 2.0 } |
| 45 | +// there's no even a assignment statement for variable in fsharp |
| 46 | +// fsharp use = to check equality |
| 47 | +let cond: bool = p1.X = 0 // [!code highlight] |
| 48 | +``` |
| 49 | + |
| 50 | +> [!NOTE] |
| 51 | +> fsharp does have ability to mark variable and field as `mutable` but definitely not recommended unless necessary. |
| 52 | +
|
| 53 | +## How to Construct Values |
| 54 | + |
| 55 | +There's two kinds of value construction in functional languages |
| 56 | + |
| 57 | +- Record |
| 58 | + - creation on literal(with inference) |
| 59 | + - direct access to members |
| 60 | + - best for pure data abstraction |
| 61 | +- Single-Case Discriminated Union |
| 62 | + - requires constructor function on creation |
| 63 | + - requires deconstruction on pattern matching to access the members |
| 64 | + - best for types that require semantic identification, validation |
| 65 | + |
| 66 | +```fsharp |
| 67 | +type Student = { name: string; age: int } // record |
| 68 | +type Person = Person of name: string * age: int // case type with constructor |
| 69 | +
|
| 70 | +let person: Person = Person("foo", 18) |
| 71 | +
|
| 72 | +printfn |
| 73 | + "%A" |
| 74 | + (match person with // requires deconstruction // [!code highlight] |
| 75 | + | Person(name, _) -> name) // [!code highlight] |
| 76 | +
|
| 77 | +let student = { name = "foo"; age = 18 } // the target type is inferred here |
| 78 | +let _ = student.name // dot accessor for records // [!code highlight] |
| 79 | +``` |
| 80 | + |
| 81 | +## Discriminated Unions |
| 82 | + |
| 83 | +**Discriminate Unions** uses new type to **wrap** over a known type to provide extra **label/description**. |
| 84 | +Such semantic difference is enforced by **nominal type system**. The following example shows how to define a `Shape` union with sub-types, |
| 85 | +the subjective relation is **not done by object inheritance** but by simple grouping since we don't need to maintain the statue thanks to **immutability**. |
| 86 | + |
| 87 | +```fsharp |
| 88 | +type Shape = |
| 89 | + // `of` clause defines constructor |
| 90 | + | Circle of float // float is type for the unnamed parameter |
| 91 | + | EquilateralTriangle of double |
| 92 | + | Square of double |
| 93 | + | Rectangle of double * double // two unnamed parameter definition typed as double, separated by * |
| 94 | +``` |
| 95 | + |
| 96 | +> [!NOTE] |
| 97 | +> There's no multiple constructors in fsharp |
| 98 | +
|
| 99 | +> [!NOTE] |
| 100 | +> Typescript as a structural typing language doesn't have discriminated union but union simply because there's no nominal system. |
| 101 | +>```ts |
| 102 | +>// NOTE: they're not wrapped as nominal types |
| 103 | +>type LogLevel = |
| 104 | +> | 'error' |
| 105 | +> | 'infor' |
| 106 | +> | 'debug' |
| 107 | +> | 'trace' |
| 108 | +>``` |
| 109 | +
|
| 110 | +## Pattern Matching |
| 111 | +
|
| 112 | +On the basis of **constructor** and **DU** we can have **Pattern Matching**. |
| 113 | +
|
| 114 | +## Functor |
| 115 | +
|
| 116 | +## Applicative |
| 117 | +
|
| 118 | +## Monad |
0 commit comments