├── .gitignore ├── Agda ├── README.md ├── Verified Functional Programming in Agda.pdf └── cubical-agda.pdf ├── Compiler ├── 402429.pdf ├── README.md └── The-Compiler-Design-Handbook.pdf ├── Coq └── README.md ├── Elixir ├── Learn Functional Programming with Elixir.pdf ├── Programming Elixir ≥ 1.6 Functional Concurrent Pragmatic Fun.pdf └── README.md ├── GC ├── README.md └── The Garbage Collection Handbook The Art of Automatic Memory Management (Chapman HallCRC Applied Algorithms and Data Structures series) by Richard Jones Antony Hosking Eliot Moss (z-lib.org).pdf ├── Haskell ├── 123.pdf ├── A_History_of_Haskell.pdf ├── Chris Allen & Julie Moronuki - Haskell Programming from First Principles.pdf ├── Generalising monads to arrows.pdf ├── HSoM.pdf ├── Haskell_Road.pdf ├── Idiom.pdf ├── Learn You a Haskell for Great Good! .pdf ├── README.md ├── Wearing_the_Hair_Shirt_A_Retrospective_on_Haskell.ppt ├── What I Wish I Knew When Learning Haskell.pdf ├── Write_Yourself_a_Scheme_in_48_Hours.pdf ├── build-systems.pdf ├── haskell2010.pdf ├── house.pdf ├── leuckerEtal.ps ├── real-world-haskell.pdf ├── type_inference_haskell_and_dt.pdf └── world.hs ├── Idris ├── IdrisDesignImplementation.pdf ├── README.md ├── Type-driven Development with Idris.pdf ├── elab-reflection.pdf ├── idris-tutorial.pdf ├── idris2.pdf └── sf-idris-2018.pdf ├── Interpreter └── README.md ├── Language and Mind.pdf ├── Lisp ├── Common Lisp.pdf ├── README.md ├── ftypes.pdf └── sicp.pdf ├── ML ├── README.md ├── dependent-ml.pdf ├── okasaki.pdf └── uw-sml.md ├── README.md ├── Rust ├── Programming Rust.pdf ├── README.md ├── Rust_Crash_Course.pdf ├── Understanding and Evolving the Rust Programming Language - RalfJung.pdf └── wrj-thesis.pdf ├── Type Theory ├── 2018-hott-intro-course.pdf ├── 2019-summer-school.pdf ├── Advanced topics in types and programming languages.pdf ├── Benjamin_C._Pierce-Types_and_Programming_Languages-The_MIT_Press(2002).pdf ├── DependentTypesAtWork.pdf ├── HoTT-UF-Agda.pdf ├── Homotopy-Type-Theory-Univalent-Foundations-of-Mathematics.pdf ├── Languages_as_Libraries.pdf ├── README.md ├── Type Theory and Formal Proof .pdf ├── Types and Programming Languages.pdf ├── cubicalmethods.pdf ├── gradual_type_theory.pdf ├── hott-intro.pdf ├── hott-online-1272-ga50f9bd.pdf ├── impldtp.pdf ├── practical_foundations_for_pl.pdf ├── propositions-as-types.pdf ├── quantitative-type-theory.pdf ├── ttfp.pdf └── typesystems.pdf └── notanum.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.hi 3 | *.o 4 | Haskell/world -------------------------------------------------------------------------------- /Agda/README.md: -------------------------------------------------------------------------------- 1 | ## Part1 2 | - [Agda Categories](https://github.com/agda/agda-categories) - A new Categories library for Agda 3 | - [HoTT Intro](https://github.com/EgbertRijke/HoTT-Intro) - An introductory course to Homotopy Type Theory 4 | - [PLFA](https://github.com/plfa/plfa.github.io) - An introduction to programming language theory in Agda 5 | - [Verified Functional Programming in Agda](https://www.morganclaypoolpublishers.com/catalog_Orig/samples/9781970001259_sample.pdf) 6 | 7 | ## Part2 8 | - [agda2hs](https://github.com/agda/agda2hs) - Compiling Agda code to readable Haskell 9 | - [frp agda](https://github.com/divipp/frp_agda) - Functional Reactive Programming with Agda -------------------------------------------------------------------------------- /Agda/Verified Functional Programming in Agda.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Agda/Verified Functional Programming in Agda.pdf -------------------------------------------------------------------------------- /Agda/cubical-agda.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Agda/cubical-agda.pdf -------------------------------------------------------------------------------- /Compiler/402429.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Compiler/402429.pdf -------------------------------------------------------------------------------- /Compiler/README.md: -------------------------------------------------------------------------------- 1 | - [Functional programming, program transformations and compiler construction](https://github.com/lambda-magic/plt.books/blob/master/Compiler/402429.pdf) 2 | - [LLVM IR Tutorial](https://github.com/Evian-Zhang/llvm-ir-tutorial) 3 | - [The Compiler Design Handbook](https://github.com/lambda-magic/plt.books/blob/master/Compiler/The-Compiler-Design-Handbook.pdf) -------------------------------------------------------------------------------- /Compiler/The-Compiler-Design-Handbook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Compiler/The-Compiler-Design-Handbook.pdf -------------------------------------------------------------------------------- /Coq/README.md: -------------------------------------------------------------------------------- 1 | 2 | - [Locally nameless representation](https://www.chargueraud.org/softs/ln/) 3 | - [Metalib](https://github.com/plclub/metalib) - Mechanize your proof! 4 | - [Software Foundations](https://softwarefoundations.cis.upenn.edu/) - Have fun with Coq! 5 | 6 | -------------------------------------------------------------------------------- /Elixir/Learn Functional Programming with Elixir.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Elixir/Learn Functional Programming with Elixir.pdf -------------------------------------------------------------------------------- /Elixir/Programming Elixir ≥ 1.6 Functional Concurrent Pragmatic Fun.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Elixir/Programming Elixir ≥ 1.6 Functional Concurrent Pragmatic Fun.pdf -------------------------------------------------------------------------------- /Elixir/README.md: -------------------------------------------------------------------------------- 1 | ## Part1 2 | 3 | - [Elixir School](https://elixirschool.com/en/) 4 | - [Functional Concurrent Pragmatic Fun](https://github.com/lambda-magic/plt.books/blob/master/Elixir/Programming%20Elixir%20%E2%89%A5%201.6%20Functional%20Concurrent%20Pragmatic%20Fun.pdf) 5 | - [Learn Functional Programming With Elixir](https://github.com/lambda-magic/plt.books/blob/master/Elixir/Learn%20Functional%20Programming%20with%20Elixir.pdf) 6 | 7 | ## Part2 8 | 9 | - [witchcraft](https://github.com/witchcrafters/witchcraft) - Monads and other dark magic for Elixir -------------------------------------------------------------------------------- /GC/README.md: -------------------------------------------------------------------------------- 1 | 2 | - [The Garbage Collection Handbook](https://github.com/lambda-magic/plt.books/blob/master/GC/The%20Garbage%20Collection%20Handbook%20The%20Art%20of%20Automatic%20Memory%20Management%20(Chapman%20%20HallCRC%20Applied%20Algorithms%20and%20Data%20Structures%20series)%20by%20Richard%20Jones%20Antony%20Hosking%20Eliot%20Moss%20(z-lib.org).pdf) -------------------------------------------------------------------------------- /GC/The Garbage Collection Handbook The Art of Automatic Memory Management (Chapman HallCRC Applied Algorithms and Data Structures series) by Richard Jones Antony Hosking Eliot Moss (z-lib.org).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/GC/The Garbage Collection Handbook The Art of Automatic Memory Management (Chapman HallCRC Applied Algorithms and Data Structures series) by Richard Jones Antony Hosking Eliot Moss (z-lib.org).pdf -------------------------------------------------------------------------------- /Haskell/123.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/123.pdf -------------------------------------------------------------------------------- /Haskell/A_History_of_Haskell.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/A_History_of_Haskell.pdf -------------------------------------------------------------------------------- /Haskell/Chris Allen & Julie Moronuki - Haskell Programming from First Principles.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/Chris Allen & Julie Moronuki - Haskell Programming from First Principles.pdf -------------------------------------------------------------------------------- /Haskell/Generalising monads to arrows.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/Generalising monads to arrows.pdf -------------------------------------------------------------------------------- /Haskell/HSoM.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/HSoM.pdf -------------------------------------------------------------------------------- /Haskell/Haskell_Road.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/Haskell_Road.pdf -------------------------------------------------------------------------------- /Haskell/Idiom.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/Idiom.pdf -------------------------------------------------------------------------------- /Haskell/Learn You a Haskell for Great Good! .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/Learn You a Haskell for Great Good! .pdf -------------------------------------------------------------------------------- /Haskell/README.md: -------------------------------------------------------------------------------- 1 | ## Part1 2 | 3 | - [A Principled Approach toOperating System Construction in Haskell](https://github.com/lambda-magic/plt.books/blob/master/Haskell/house.pdf) 4 | - [Anatomy of Programming Languages](https://www.cs.utexas.edu/~wcook/anatomy/) - Just create a simple language 5 | - [Functional Programming Course](https://github.com/system-f/fp-course) 6 | - [Learn You a Haskell for Great Good!](http://learnyouahaskell.com/) | [zh-cn](https://learnyouahaskell.mno2.org/zh-cn) 7 | - [Lambda the ultimate Pattern Factory](https://github.com/thma/LtuPatternFactory) - Typeclassopedia vs Software Design Patterns 8 | - [Magic Haskell](https://github.com/winterland1989/magic-haskell) - Tsinghua University Haskell Courses 9 | - [Polysemy Clean Architecture](https://github.com/thma/PolysemyCleanArchitecture) 10 | - [Real World Haskell](https://github.com/lambda-magic/plt.books/blob/master/Haskell/real-world-haskell.pdf) 11 | - [The Haskell Road to Logic, Math and Programming](https://github.com/lambda-magic/plt.books/blob/master/Haskell/Haskell_Road.pdf) 12 | - [The Haskell School of Music](https://www.cs.yale.edu/homes/hudak/Papers/HSoM.pdf) - From Signals to Symphonies 13 | - [What I Wish I Knew When Learning Haskell](https://github.com/sdiehl/wiwinwlh) 14 | - [Why Haskell Matters](https://github.com/thma/WhyHaskellMatters) 15 | - [Write you a Haskell](https://github.com/sdiehl/write-you-a-haskell) - Building a modern functional compiler from first principles 16 | - [Write Yourself a Scheme in 48 Hours](https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours) 17 | 18 | ## Part2 19 | 20 | - [Cλash Compiler](https://github.com/clash-lang/clash-compiler) - Haskell to VHDL/Verilog/SystemVerilog compiler 21 | - [Csound Expression](https://github.com/spell-music/csound-expression) - Haskell Framework for Electronic Music 22 | - [Cubical TT](https://github.com/mortberg/cubicaltt) - Experimental implementation of Cubical Type Theory 23 | - [Detexify Backend](https://github.com/kirel/detexify-hs-backend) - LaTeX handwritten symbol recognition 24 | - [Dth](https://github.com/sweirich/dth) - Examples of Dependently-typed programs in Haskell 25 | - [Distributed Process](https://github.com/haskell-distributed/distributed-process) - Erlang-style concurrent and distributed programming in Haskell 26 | - [IHP](https://github.com/digitallyinduced/ihp) - λ IHP is a modern batteries-included Web Framework, built on top of Haskell and Nix 27 | - [GHC Proofs](https://github.com/nomeata/ghc-proofs) - Let GHC prove program equations for you 28 | - [Haxl](https://github.com/facebook/Haxl) - A Haskell library that simplifies access to remote data, such as databases or web-based services 29 | - [HerbiePlugin](https://github.com/mikeizbicki/HerbiePlugin) - GHC plugin that improves Haskell code's numerical stability 30 | - [hos](https://github.com/tathougies/hos) - The functional Haskell kernel 31 | - [lambdapi](https://github.com/ilya-klyuchnikov/lambdapi) - Dependently Typed Lambda Calculus in Haskell 32 | - [Kontiki](https://github.com/NicolasT/kontiki) - An implementation of the Raft consensus protocol 33 | - [Mezzo](https://github.com/DimaSamoz/mezzo) - A Haskell library for typesafe music composition 34 | - [MIPS Simulator](https://github.com/skyzh/mips-simulator) - A 5-stage pipeline MIPS CPU design in Haskell 35 | - [Pandoc](https://github.com/jgm/pandoc) - Universal markup converter 36 | - [pLam](https://github.com/slovnicki/pLam) - An interpreter for learning and exploring pure λ-calculus 37 | - [PureScript](https://github.com/purescript/purescript) - A strongly-typed language that compiles to JavaScript 38 | - [Xmonad](https://github.com/xmonad/xmonad) - A small but functional ICCCM-compliant tiling window manager -------------------------------------------------------------------------------- /Haskell/Wearing_the_Hair_Shirt_A_Retrospective_on_Haskell.ppt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/Wearing_the_Hair_Shirt_A_Retrospective_on_Haskell.ppt -------------------------------------------------------------------------------- /Haskell/What I Wish I Knew When Learning Haskell.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/What I Wish I Knew When Learning Haskell.pdf -------------------------------------------------------------------------------- /Haskell/Write_Yourself_a_Scheme_in_48_Hours.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/Write_Yourself_a_Scheme_in_48_Hours.pdf -------------------------------------------------------------------------------- /Haskell/build-systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/build-systems.pdf -------------------------------------------------------------------------------- /Haskell/haskell2010.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/haskell2010.pdf -------------------------------------------------------------------------------- /Haskell/house.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/house.pdf -------------------------------------------------------------------------------- /Haskell/real-world-haskell.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/real-world-haskell.pdf -------------------------------------------------------------------------------- /Haskell/type_inference_haskell_and_dt.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Haskell/type_inference_haskell_and_dt.pdf -------------------------------------------------------------------------------- /Haskell/world.hs: -------------------------------------------------------------------------------- 1 | main :: IO () 2 | main = putStrLn "Hello, World!" 3 | 4 | -------------------------------------------------------------------------------- /Idris/IdrisDesignImplementation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Idris/IdrisDesignImplementation.pdf -------------------------------------------------------------------------------- /Idris/README.md: -------------------------------------------------------------------------------- 1 | 2 | - [Idris 2: Quantitative Type Theory in Actio](https://github.com/lambda-magic/plt.books/blob/master/Idris/idris2.pdf) 3 | - [Software Foundations in Idris](https://github.com/idris-hackers/software-foundations) 4 | - [Type Driven Development with Idris](https://livebook.manning.com/book/type-driven-development-with-idris/type-driven-development-with-idris/) -------------------------------------------------------------------------------- /Idris/Type-driven Development with Idris.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Idris/Type-driven Development with Idris.pdf -------------------------------------------------------------------------------- /Idris/elab-reflection.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Idris/elab-reflection.pdf -------------------------------------------------------------------------------- /Idris/idris-tutorial.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Idris/idris-tutorial.pdf -------------------------------------------------------------------------------- /Idris/idris2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Idris/idris2.pdf -------------------------------------------------------------------------------- /Idris/sf-idris-2018.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Idris/sf-idris-2018.pdf -------------------------------------------------------------------------------- /Interpreter/README.md: -------------------------------------------------------------------------------- 1 | 2 | - [Crafting Interpreters](http://craftinginterpreters.com/) - A handbook for making programming languages -------------------------------------------------------------------------------- /Language and Mind.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Language and Mind.pdf -------------------------------------------------------------------------------- /Lisp/Common Lisp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Lisp/Common Lisp.pdf -------------------------------------------------------------------------------- /Lisp/README.md: -------------------------------------------------------------------------------- 1 | 2 | - [Ftypes: Structured foreign types](https://github.com/lambda-magic/plt.books/blob/master/Lisp/ftypes.pdf) 3 | - [SICP Racket](https://github.com/codereport/SICP-2020) - Programming Languages Virtual Meetup coverage of the Structure and Interpretation of Computer Programs textbook. -------------------------------------------------------------------------------- /Lisp/ftypes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Lisp/ftypes.pdf -------------------------------------------------------------------------------- /Lisp/sicp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Lisp/sicp.pdf -------------------------------------------------------------------------------- /ML/README.md: -------------------------------------------------------------------------------- 1 | 2 | - [Purely Functional Data Structure](https://github.com/lambda-magic/plt.books/blob/master/ML/okasaki.pdf) -------------------------------------------------------------------------------- /ML/dependent-ml.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/ML/dependent-ml.pdf -------------------------------------------------------------------------------- /ML/okasaki.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/ML/okasaki.pdf -------------------------------------------------------------------------------- /ML/uw-sml.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Standard ML 3 | date: 2020-09-16 4 | tags: 5 | - Polymorphic λ 6 | --- 7 | 8 | ### ML Variable Bindings and Expressions 9 | 10 | ```sml 11 | val z = 3; 12 | (* static environment: z : int *) 13 | (* dynamic environment: z --> 3 *) 14 | 15 | val w = z + 1; 16 | (* static environment: z : int, w : int *) 17 | (* dynamic environment: z --> 3, w --> 4 *) 18 | ``` 19 | 20 | 1. The semantics 21 | - Syntax is just how you write something 22 | - Semantics is what something means 23 | - Type-checking (before program runs) 24 | - Evaluation (as program runs) 25 | - For variable bindings: 26 | - Type-check expression and extend static environment 27 | - Evaluate expression and extend dynamic environment 28 | 29 | 2. Rules for expressions: 30 | - Every kind of expression has: 31 | - Syntax 32 | - Type-checking rules. Produce a type or fails. 33 | - Evaluation rules (used only on things that type-check). 34 | Produce a value (or exception or infinite-loop). 35 | 36 | 3. Reasons for shadowing: 37 | ```sml 38 | val a = 1 39 | val b = a (* b is bound to 1 *) 40 | val a = 2 41 | ``` 42 | - Expressions in variable bindings are evaluated **eagerly** 43 | - Before the variable binding finishes 44 | - Afterwards, the expression producing the value is irrelevant 45 | - There is no way to assign to a variable in ML 46 | - Can only shadow in a later environment 47 | 48 | ### ML Functions 49 | 50 | 1. Functions informally 51 | ```sml 52 | fun pow (x : int, y : int) = 53 | if y = 0 54 | then 1 55 | else x * pow (x, y - 1) 56 | ``` 57 | - Cannot refer to later function bindings 58 | - Simply ML`s rule 59 | - Helper functions must come before their uses 60 | - Need special construct for mutual recursion 61 | 62 | 2. Function bindings formally 63 | - Syntax: `fun x0 (x1 : t1, ..., xn : tn) = e` 64 | - Type-checking: 65 | - Add binding `x0 : (t1 * ... * tn) -> t` if: 66 | - Can type-check body `e` to have type `t` in the static environment containing: 67 | - Enclosing static environment (earlier bindings) 68 | - `x1 : t1, ..., xn : tn` (arguments with their types) 69 | - `x0 : (t1 * ... * tn) -> t` (for recursion) 70 | - Evaluation: 71 | - A function is a value — we simply add x0 to the environment as a function that can be called later. 72 | - As expected for recursion, x0 is in the dynamic environment in the function body and for subsequent bindings. 73 | 74 | 75 | 3. Function calls formally 76 | - Syntax: `e0 (e1,...,en)` with the parentheses optional if there is exactly one argument. 77 | - Type-checking: require that `e0` has a type that looks like `t1 * ... * tn -> t` and for 1 ≤ i ≤ n, `ei` has type `ti`. Then the whole call has type `t`. 78 | - Evaluation: 79 | - Evaluate `e0` to `fun x0 (x1 : t1, ..., xn : tn) = e`. Since call type-checked, result will be a function. Evaluate arguments to values `v1, ..., vn` (Under current dynamic environment). 80 | - Result is evaluation of `e` in an environment extended to map `x1` to `v1, ..., xn` to `vn` (An environment is actually the environment where the function was defined, and includes `x0` for recursion). 81 | 82 | ### Pairs and Other Tuples 83 | 84 | 1. Build 85 | - Syntax: `(e1, e2)` 86 | - Type-checking: if `e1` has type `ta` and `e2` has type `tb`, then the pair expression has type `ta * tb` - a new kind of type. 87 | - Evaluation: evaluate `e1` to `v1` and `e2` to `v2`, result is `(v1, v2)` - a pair of values is a value. 88 | 89 | 2. Access 90 | - Syntax: `#1 e` and `#2 e` 91 | - Type-checking: if `e` has type `ta * tb`, then `#1 e` has type `ta` and `#2 e` has type `tb`. 92 | - Evaluation: evaluate `e` to a pair of values and return first or second piece. 93 | 94 | ```sml 95 | fun swap (pr : int * bool) = 96 | (#2 pr, #1 pr) 97 | 98 | fun sum_two_pairs (pr1 : int * int, pr2 : int * int) = 99 | (#1 pr1) + (#2 pr1) + (#1 pr2) + (#2 pr2) 100 | 101 | fun div_mod (x: int, y: int) = 102 | (x div y, x mod y) 103 | 104 | fun sort_pair (pr : int * int) = 105 | if (#1 pr) < (#2 pr) 106 | then pr 107 | else (#2 pr, #1 pr) 108 | ``` 109 | 110 | 3. Tuple is a generalization of pairs. 111 | - Pairs and tuples can be nested (implied by the syntax and semantics) 112 | 113 | ```sml 114 | val x1 = (7, (true, 9)) 115 | val x2 = #1 (#2 x1) 116 | ``` 117 | 118 | ### Lists 119 | 120 | 1. Build: `[v1, v2, ... ,vn]`, `::` pronounced **cons** 121 | 2. Access: `null`, `hd`, `tl` 122 | 3. Functions over lists are usually recursive, only way to get to all the elements. 123 | 124 | ```sml 125 | fun sum_list (xs : int list) = 126 | if null xs 127 | then 0 128 | else hd(xs) + sum_list(tl xs) 129 | 130 | fun countdown (x : int) = 131 | if x = 0 132 | then [] 133 | else x :: countdown(x - 1) 134 | 135 | fun append (xs : int list, ys : int list) = 136 | if null xs 137 | then ys 138 | else (hd xs) :: append(tl xs, ys) 139 | ``` 140 | 141 | ### Let Expressions 142 | 143 | ```sml 144 | fun countup_from (x : int) = 145 | let 146 | fun count (from : int) = 147 | if from = x 148 | then x :: [] 149 | else from :: count (from + 1) 150 | in 151 | count (1) 152 | end 153 | 154 | fun max (xs : int list) = 155 | if null xs 156 | then 0 157 | else if null (tl xs) 158 | then hd xs 159 | else 160 | (* for style, could also use a let-binding for (hd xs) *) 161 | let val tl_ans = max (tl xs) 162 | in 163 | if hd xs > tl_ans 164 | then hd xs 165 | else tl_ans 166 | end 167 | ``` 168 | 1. Syntax: `let b1 b2 ... bn in e end`. Each `bi` is any binding and `e` is any expression. 169 | 2. Type-checking: Type-check each `bi` and `e` in a static environment that includes the previous bindings. Type of whole let-expression is the type of `e`. 170 | 3. Evaluation: Evaluate each `bi` and `e` in a dynamic environment that includes the previous bindings. Result of whole let-expression is result of evaluating `e`. 171 | 4. Scope: where a binding is in the environment. Only in later bindings and body of the let-expression. 172 | 5. The key to improve efficiency of recursion is not to do repeated work that might do repeated work. Saving recursive results in local bindings is essential. 173 | 174 | ### Options 175 | 176 | ```sml 177 | fun max1 (xs : int list) = 178 | if null xs 179 | then NONE 180 | else 181 | let val tl_ans = max1 (tl xs) 182 | in if isSome tl_ans andalso valOf tl_ans > hd xs 183 | then tl_ans 184 | else SOME (hd xs) 185 | end 186 | ``` 187 | 1. Building: `NONE` has type `'a option`, `SOME e` has type `t option` if `e` has type `t`. 188 | 2. Accessing: `isSome` has type `'a option -> bool`, `valOf` has type `'a option -> 'a` (exception if given `NONE`). 189 | 190 | ### Booleans and Comparison Operations 191 | 192 | 1. Syntax: `e1 andalso e2`, `e1 orelse e2`, `not e1`. 193 | 2. Short-circuiting evaluation means `andalso` and `orelse` are not functions, but `not` is just a pre-defined function. 194 | 3. `=` `<>` can be used with any equality type but not with `real`. 195 | 196 | ### No Mutation: ML vs. Imperative Languages 197 | 198 | 1. In ML, we create aliases all the time without thinking about it because it is impossible to tell where there is aliasing. 199 | - Example: `tl` is constant time; does not copy rest of the list. 200 | - So do not worry and focus on the algorithm. 201 | 2. In language with mutable data (e.g. Java), programmers are obsessed with aliasing and object identity. 202 | - They have to be (!) so that subsequent assignments affect the right parts of the program. 203 | - Often crucial to make copies in just the right places. 204 | 3. Reference (alias) vs. copy does not matter if code is immutable. 205 | 206 | ### Pieces of a Language 207 | 208 | 1. Syntax 209 | 2. Semantics (evaluation rules) 210 | 3. Idioms (typical patterns for using language features to express the computation) 211 | 4. Libraries 212 | 5. Tools 213 | 214 | ### Building Compound Types 215 | 216 | Three most important type building-blocks in any language: 217 | 1. Each of: A `t` value contains values of each of `t1 t2 ... tn`. Such as tuples and records (idea of syntactic sugar and connection with tuples). 218 | 2. One of: A `t` value contains values of ont of `t1 t2 ... tn`. Such as option and a type that contains an int or string (will lead to pattern-matching). 219 | 3. Self reference: A `t` value can refer to other `t` values. 220 | 221 | ### Records 222 | 223 | 1. Record values have fields (any name) holding values `{f1 = v1, ... , fn = vn}`. Record types have fields holding types `{f1 : t1, ..., fn : tn}`. The order of fields in a record value of type never matters. REPL alphabetizes fields just for consistency. 224 | 2. Building records: `{f1 = e1, ..., fn = en}` 225 | 3. Accessing pieces: `#myfieldname e` 226 | 4. Evaluation rules and type-checking as expected. 227 | 5. A common decision for a construct's syntax is whether to refer to things by position (as in tuples) or by some (field) name (as with records). 228 | - A common hybrid is like with Java method arguments (and ML functions are used so far): 229 | - Caller uses position 230 | - Callee uses variables 231 | - Could do it differently 232 | 6. Tuples are just syntactic sugar for records with fields named 1, 2, ... 233 | - Syntactic: Can describe the semantics entirely by the corresponding record syntax. 234 | - They simplify understanding / implementing the langauge. 235 | 236 | ### Datatype Bindings 237 | 238 | 1. A way to make one-of types: 239 | - A `datatype` binding 240 | ```sml 241 | datatype mytype = 242 | TwoInts of int * int 243 | | Str of string 244 | | Pizza 245 | ``` 246 | - Adds a new type `mytype` to the environment 247 | - Adds constructors to the environment: `TwoInts`, `Str` and `Pizza` 248 | - `TwoInts : int * int -> mytype` 249 | - `Str : string -> mytype` 250 | - `Pizza : mytype` 251 | 2. A constructor is (among other things), a **function** that makes values of the new type (or is a value of the new type): 252 | - Any value of type `mytype` is made from one of the constructors. 253 | - The value contains: 254 | - A tag for which constructor (e.g. TwoInts) 255 | - The corresponding data (e.g. (7, 9)) 256 | 3. In many other contexts, these datatypes are called tagged unions. 257 | 4. There are two aspects to accessing a datatype value: 258 | - Check what variant it is (what constructor made it). `null` and `isSome` check variants. 259 | - Extract the data (if that variant has any). `hd` `tl` `valOf` extract data (raise exception on wrong variant). 260 | 5. Useful datatypes: 261 | - Enumerations, including carrying other data. 262 | - Alternate ways of identifying real-world things/people. 263 | - Expression trees. This is an example using self-reference: 264 | ```sml 265 | datatype exp = 266 | Constant of int 267 | | Negate of exp 268 | | Add of exp * exp 269 | | Multiply of exp * exp 270 | 271 | (* functions over recursive datatypes are usually recursive *) 272 | 273 | fun eval e = 274 | case e of 275 | Constant i => i 276 | | Negate e2 => ~ (eval e2) 277 | | Add (e1, e2) => (eval e1) + (eval e2) 278 | | Multiply (e1, e2) => (eval e1) * (eval e2) 279 | 280 | fun number_of_adds e = 281 | case e of 282 | Constant i => 0 283 | | Negate e2 => number_of_adds e2 284 | | Add (e1, e2) => 1 + number_of_adds e1 + number_of_adds e2 285 | | Multiply (e1, e2) => number_of_adds e1 + number_of_adds e2 286 | ``` 287 | - Lists and Options are datatypes. 288 | ```sml 289 | datatype my_int_list = Empty | Cons of int * my_int_list 290 | 291 | fun inc_or_zero intoption = 292 | case intoption of 293 | NONE => 0 294 | | SOME i => i + 1 295 | 296 | fun append (xs, ys) = 297 | case xs of 298 | [] => ys 299 | | x :: xs' => x :: append (xs', ys) 300 | ``` 301 | 6. Polymorphic Datatypes: 302 | - Syntax: put one or more type variables before datatype name. Can use these type variables in constructor definitions. Binding then introduces a type constructor, not a type. (Must say `int mylist`, `'a mylist`, not `mylist`). 303 | ```sml 304 | datatype 'a mylist = Empty | Cons of 'a * 'a mylist 305 | 306 | datatype ('a, 'b) tree = 307 | Node of 'a * ('a, 'b) tree * ('a, 'b) tree 308 | | Leaf of 'b 309 | ``` 310 | - Use constructors and case expressions as usual. No change to evaluation rules. Type-checking will make sure types are used consistently. For example, cannot mix element types of list. Functions will be polymorphic or not based on how data is used. 311 | 312 | ### Case Expressions 313 | 314 | 1. ML combines the two aspects of accessing a one-of value with a case expression and pattern-matching. 315 | 316 | ```sml 317 | fun f (x : mytype) = 318 | case x of 319 | Pizza => 3 320 | | Str s => 8 321 | | TwoInts (i1, i2) => i1 + i2 322 | ``` 323 | 324 | - A multi-branch conditional to pick branch based on variant. 325 | - Extracts data and binds to variables local to that branch. 326 | - Type-checking: all branches must have same type. 327 | - Evaluation: evaluate between case ... of and the right branch. 328 | - Patterns are not expressions: We do not evaluate them. We see if the result of `e0` matches them. 329 | 330 | ### Type Synonyms 331 | 332 | 1. Creating new types: 333 | - A datatype binding introduces a new type name. 334 | - Distinct from all existing types. 335 | - Only way to create values of the new type is the constructors. 336 | - A type synonym is a new kind of binding `type aname = t`. 337 | - Just creates another name for a type. 338 | - The type and the name are interchangeable in every way. 339 | - Do not worry about that REPL prints: picks what it wants just like it picks the order of record field names. 340 | 2. A convenience for talking about types. Related to modularity. 341 | 342 | ### Each of Pattern Matching 343 | 344 | 1. Pattern matching also works for records and tuples. 345 | 2. Val-binding patterns: variables are just one kind of pattern. 346 | 3. A function argument can also be a pattern. What we call multi-argument functions are just functions taking one tuple argument, implemented with a tuple pattern in the function binding. Zero arguments is the unit pattern () matching the unit value (). 347 | 348 | ```sml 349 | fun sum_triple triple = 350 | case triple of 351 | (x, y, z) => x + y + z 352 | 353 | fun sum_triple1 triple = 354 | let val (x, y, z) = triple 355 | in 356 | x + y + z 357 | end 358 | 359 | fun sum_triple2 (x, y, z) = x + y + z 360 | ``` 361 | 362 | ### Polymorphic and Equality types 363 | 364 | 1. The **more general** rule: A type t1 is more general than the type t2 if you can take t1, replace its type variables consistently, and get t2. 365 | - Example: replace each `'a` with `int * int` 366 | - Example: replace each `'b` with `'a` and each `'a` with `'a` 367 | 2. Can combine the **more general** rule with rules for equivalence: 368 | - Use of type synonyms does not matter 369 | - Order of field names does not matter 370 | 3. Type variables with a second quote such as `''a list * ''a -> bool` are **equality types** that arise from using the = operator. The = operator works on lots of types: int, string, tuples containing all equality types... But not all types: function types, real... 371 | 4. The rules for more general are exactly the same except you have to replace an equality-type variable with a type taht can be used with =. 372 | 373 | ```sml 374 | (* ''a * ''a -> string *) 375 | fun same_thing (x, y) = 376 | if x = y then "yes" else "no" 377 | ``` 378 | 379 | ### Nested Patterns 380 | 381 | ```sml 382 | fun zip list_triple = 383 | case list_triple of 384 | ([], [], []) => [] 385 | | (hd1 :: tl1, hd2 :: tl2, hd3 :: tl3) => 386 | (hd1, hd2, hd3) :: zip (tl1, tl2, tl3) 387 | | _ => raise ListLengthMismatch 388 | 389 | fun unzip lst = 390 | case lst of 391 | [] => ([], [], []) 392 | | (a, b, c) :: tl => 393 | let val (l1, l2, l3) = unzip tl 394 | in (a :: l1, b :: l2, c :: l3) end 395 | 396 | fun multsign (x1, x2) = (* int * int -> sgn *) 397 | let fun sign x = if x = 0 then Z else if x > 0 then P else N 398 | in 399 | case (sign x1, sign x2) of 400 | (Z, _) => Z 401 | | (_, Z) => Z 402 | | (P, P) => P 403 | | (N, N) => P 404 | | (N, P) => N 405 | | (P, N) => N 406 | end 407 | ``` 408 | 409 | 1. We can nest patterns as deep as we want. The full meaning of pattern matching is to compare a pattern against a value for the same shape and bind variables to the right parts. 410 | 2. A common idiom is matching against a tuple of datatypes to compare them. 411 | 3. Wildcards are good style: use them instead of variables when you do not need the data. 412 | 4. The semantics for pattern-matching takes a pattern p and a value v and decides does it match and if so what variable bindings are introduced. Since patterns can nest, the definition is elegantly recursive, with a separate rule for each kind of pattern. 413 | 5. Function patterns: syntactic sugar of case expression. 414 | 415 | ```sml 416 | fun f p1 = e1 417 | | f p2 = e2 418 | | f pn = en 419 | 420 | fun append ([], ys) = ys 421 | | append (x :: xs', ys) = x :: append (xs', ys) 422 | ``` 423 | 424 | ### Exceptions 425 | 426 | ```sml 427 | fun maxlist (xs, ex) = (* int list * exn -> int *) 428 | case xs of 429 | [] => raise ex 430 | | x :: [] => x 431 | | x :: xs' => Int.max(x, maxlist (xs', ex)) 432 | 433 | exception MyException of int * int 434 | exception MySimpleException 435 | 436 | val x = maxlist ([3, 4, 5], MySimpleException) 437 | handle MySimpleException => 0 438 | 439 | val w = maxlist ([], MyException (2, 3)) 440 | handle MyException (x, y) => x + y 441 | ``` 442 | 443 | 1. Exceptions are a lot like datatype constructors. 444 | 2. Declaring an exception makes adds a constructor for type `exn`. 445 | 3. Can pass values of `exn` anywhere (e.g. function arguments). 446 | 4. Handle can have multiple branches with patterns for type `exn`. 447 | 448 | ### Tail Recursion 449 | 450 | ```sml 451 | fun fact n = 452 | let fun aux (n, acc) = 453 | if n = 0 454 | then acc 455 | else aux (n - 1, acc * n) 456 | in aux (n, 1) end 457 | 458 | fun rev' xs = 459 | case xs of 460 | [] => [] 461 | (* append must traverse the first list *) 462 | | x :: xs' => (rev' xs') @ [x] 463 | 464 | fun rev xs = 465 | let fun aux (xs, acc) = 466 | case xs of 467 | [] => acc 468 | | x :: xs' => aux (xs', x :: acc) 469 | in aux (xs, []) end 470 | ``` 471 | 472 | 1. While a program runs, there is a call stack of function calls that have started but not yet returned. 473 | - Calling a function f pushes an instance of f on the stack. 474 | - When a call to f finished, it is popped from the stack. 475 | - These stack-frames store information like the value of local variables and what is left to do in function. Due to recursion, multiple stack-frames may be calls to the same function. 476 | 2. An optimization: It is unnecessary to keep around a stack-frame just so it can get a callee's result and return it without any further evaluaion. ML recognizes these tail calls in the compiler and treats them differently: 477 | - Pop the caller before the call, allowing callee to reuse the same stack space (tail-calls: nothing left for caller to do, so the pop caller). 478 | - Along with other optimizations, as efficient as a loop. 479 | ![](../images/sml/tail.png) 480 | 3. Accumulators for tail recursion: 481 | - Tail-recursive: recursive calls are tail-calls. 482 | - A methodology that can often guide this transformation: Create a helper function that takes an accumulator. Old base case becomes initial accumulator. New base case becomes final accumulator. 483 | 4. There are certainly cases where recursive functions cannot be evaluated in a constant amount of space. Most obvious examples are functions that process trees. In these cases, the natural recursive approach is the way to go. 484 | 5. A tail call is a function call in tail position. If an expression is not in tail position, then no subexpressions are. The nothing left for caller to do intuition usually suffices. 485 | 486 | ### First-Class Functions 487 | 488 | ```sml 489 | fun n_times (f, n, x) = 490 | if n = 0 491 | then x 492 | else f (n_times (f, n - 1, x)) 493 | 494 | fun increment x = x + 1 495 | fun double x = x + x 496 | 497 | val x1 = n_times (double, 4, 7) 498 | val x2 = n_times (increment, 4, 7) 499 | val x3 = n_times (tl, 2, [4, 8, 12, 16]) 500 | 501 | fun triple_n_times (n, x) = 502 | n_times ((fn x => 3 * x), n, x) 503 | ``` 504 | 505 | 1. Functions are values too. Higher order functions are the most useful ones when you want to abstract over what to compute with. 506 | 2. Function closure: Functions can use bindings from outside the function definition (in scope where function is defined). 507 | 3. Anonymous functions: most commonly used as argument to a higher-order function. Do not need a name just to pass a function. Can not use an anonymous function for a recursive function. If not for recursion, `fun` bindings would be syntatic sugar for `val` bindings and anonymous functions. 508 | ```sml 509 | fun triple x = 3 * x 510 | val triple = fn y => 3 * y 511 | ``` 512 | 4. Map and filter: predefined in `List`. 513 | ```sml 514 | (* ('a -> 'b) * 'a list -> 'b list *) 515 | fun map (f, xs) = 516 | case xs of 517 | [] => [] 518 | | x :: xs' => (f x) :: map (f, xs') 519 | 520 | val x1 = map ((fn x => x + 1), [4, 8, 12]) 521 | val x2 = map (hd, [[1, 2], [3, 4], [5, 6, 7]]) 522 | 523 | (* ('a -> bool) * 'a list -> 'a list *) 524 | fun filter (f, xs) = 525 | case xs of 526 | [] => [] 527 | | x :: xs' => if f x 528 | then x :: (filter (f, xs')) 529 | else filter (f, xs') 530 | 531 | fun is_even v = 532 | (v mod 2 = 0) 533 | 534 | fun all_even xs = filter (is_even, xs) 535 | 536 | fun all_even_snd xs = filter ((fn (_, v) => is_even v), xs) 537 | ``` 538 | 5. Fold: (synonyms / close relatives reduce, inject, etc.) is another very famous iterator over recursive structures. Accumulates an answer by repeatedly applying f to answer so far. These iterator-like functions are not built into SML. It is just a programming pattern. This pattern separates recursive traversal from data processing. Can reuse same traversal for different data processing. Can reuse same data processing for different data structures. 539 | ```sml 540 | fun fold (f, acc, xs) = 541 | case xs of 542 | [] => acc 543 | | x :: xs => fold (f, f (acc, x), xs) 544 | ``` 545 | 546 | ### Lexical Scope 547 | 548 | 1. Closures: 549 | ```sml 550 | val x = 1 (* x maps to 1 *) 551 | fun f y = x + y (* f maps to a function that adds 1 to its argument *) 552 | val x = 2 (* x maps to 2 *) 553 | val y = 3 (* y maps to 3 *) 554 | val z = f (x + y) (* call the function defined on line 4 with 5 *) 555 | (* z maps to 6 *) 556 | ``` 557 | - How can functions be evaluated in old enviroments that are not around anymore? The language implementation keeps them around as necessary. Can define the semantics of functions as follows: 558 | - A function value has two parts: the code and the environment that was current when the function was defined. 559 | - This is a pair but unlike ML pairs. You cannot access the pieces. All you can do is call this pair. This pair is called a function closure. 560 | - A call evaluates the code part in the environment part (extended with the function argument). 561 | - Line 2 creates a closure and binds f to it. 562 | - Code: take y and body x + y 563 | - Environment: x maps to 1. (Plus whatever else is in scope, including f for recursion) 564 | - Line 5 calls the closure defined in line 2 with 5. So body evaluated in environment x maps to 1 extended with y maps to 5. 565 | 2. Lexical scope and higher-order functions: the rule stays the same. A function body is evaluated in the environment where the function was defined. (Extended with the function argument). Nothing changes to this rule when we take and return functions. (But the environment may involve nested let-expressions, not just the top-level sequence of bindings). Makes first-class functions much more powerful. 566 | 3. Why lexical scope: 567 | - Lexical scope: use environment where function is defined. 568 | - Dynamic scope: use environment where function is called. 569 | - Function meaning does not depend on variable names used: 570 | - Can change body of f to use q everywhere instead of x. 571 | - Can remove unused variables. 572 | - Functions can be type-checked and reasoned about where defined. 573 | - Closures can easily store the data they need. 574 | - Lexical scope for variables is definitely the right default (very common across languages). Dynamic scope is occassionally convenient in some situations. So some languages (e.g. Racket) have special ways to do it. Exception handling is more like dynamic scope. `raise e` transfers control to the current innermost handler. Does not have to be syntactically inside a handle expression (and usually is not). 575 | 576 | ### Closures and Recomputation 577 | 578 | 1. When things evaluate: a function body is not evaluated until the function is called. A function body is evaluated every time the function is called. A variable binding evaluates its expression when the bining is evaluated, not every time the variable is used. With closures, this means we can avoid repeating computations that do not depend on function arguments. 579 | ```sml 580 | fun filter (f, xs) = 581 | case xs of 582 | [] => [] 583 | | x :: xs' => if f x 584 | then x :: filter (f, xs') 585 | else filter (f, xs') 586 | 587 | fun allShorterThan1 (xs, s) = 588 | filter (fn x => String.size x < String.size s, xs) 589 | 590 | fun allShorterThan2 (xs, s) = 591 | let 592 | val i = String.size s 593 | in 594 | filter (fn x => String.size x < i, xs) 595 | end 596 | ``` 597 | 2. Closure Idioms: 598 | - Pass functions with private data to iterators 599 | - Combining functions (e.g. composition) 600 | ```sml 601 | fun compose (f, g) = fn x => f (g x) 602 | fun sqrt_of_abs i = Math.sqrt (Real.fromInt (abs i)) 603 | fun sqrt_of_abs' i = (Math.sqrt o Real.fromInt o abs) i 604 | val sqrt_of_abs'' = Math.sqrt o Real.fromInt o abs 605 | 606 | infix !> 607 | fun x !> f = f x 608 | fun sqrt_of_abs''' i = i !> abs !> Real.fromInt !> Math.sqrt 609 | 610 | fun backup1 (f, g) = fn x => case f x of 611 | NONE => g x 612 | | SOME y => y 613 | 614 | fun backup2 (f, g) = fn x => f x handle _ => g x 615 | ``` 616 | - Currying (multi-arg functions and partial application). Efficiency: SML/NJ compiles tuples more efficiently. But many other functional language implementations do better with currying (OCaml, F#, Haskell). 617 | ```sml 618 | val sorted3 = fn x => fn y => fn z => z >= y andalso y >= x 619 | 620 | val t1 = ((sorted3 7) 9) 11 621 | val t2 = sorted3 7 9 11 622 | 623 | fun sorted3_nicer x y z = z >= y andalso y >= x 624 | 625 | fun fold f acc xs = 626 | case xs of 627 | [] => acc 628 | | x :: xs' => fold f (f(acc, x)) xs' 629 | 630 | fun sum xs = fold (fn (x, y) => x + y) 0 xs 631 | 632 | fun exists predicate xs = 633 | case xs of 634 | [] => false 635 | | x :: xs' => predicate x orelse exists predicate xs' 636 | 637 | val hasZero = exists (fn x => x = 0) 638 | 639 | fun curry f = fn x => fn y => f (x, y) 640 | fun curry1 f x y = f (x, y) 641 | 642 | fun uncurry f (x, y) = f x y 643 | ``` 644 | - Callbacks (e.g. in reactive programming): Library takes functions to apply later, when an event occurs. 645 | - Implementing an ADT with a record of functions. 646 | 3. Closure idioms without closures: 647 | - Higher-order programming is great. 648 | ```sml 649 | datatype 'a mylist = Cons of 'a * ('a mylist) | Empty 650 | 651 | fun map f xs = 652 | case xs of 653 | Empty => Empty 654 | | Cons (x, xs) => Cons (f x, map f xs) 655 | 656 | fun filter f xs = 657 | case xs of 658 | Empty => Empty 659 | | Cons (x, xs) => if f x 660 | then Cons (x, filter f xs) 661 | else filter f xs 662 | 663 | fun length xs = 664 | case xs of 665 | Empty => 0 666 | | Cons (x, xs) => 1 + length xs 667 | 668 | val doubleAll = map (fn x => x * 2) 669 | 670 | fun countNs (xs, n : int) = length (filter (fn x => x = n) xs) 671 | ``` 672 | - In OOP with one-method interfaces. An interface is a named [polymorphic] type. An object with one method can serve as a closure. 673 | ```java 674 | interface Func { 675 | B m(A x); 676 | } 677 | 678 | interface Pred { 679 | boolean m(A x); 680 | } 681 | 682 | class List { 683 | T head; 684 | List tail; 685 | 686 | List(T x, List xs) { 687 | head = x; 688 | tail = xs; 689 | } 690 | 691 | static List map(Func f, List xs) { 692 | if (xs == null) 693 | return null; 694 | return new List(f.m(xs.head), map(f, xs.tail)); 695 | } 696 | 697 | static List filter(Pred f, List xs) { 698 | if (xs == null) 699 | return null; 700 | if (f.m(xs.head)) 701 | return new List(xs.head, filter(f, xs.tail)); 702 | return filter(f, xs.tail); 703 | } 704 | 705 | static int length(List xs) { 706 | int ans = 0; 707 | while (xs != null) { 708 | ++ans; 709 | xs = xs.tail; 710 | } 711 | return ans; 712 | } 713 | } 714 | 715 | public class Clients { 716 | static List doubleAll(List xs) { 717 | return List.map((new Func() { 718 | public Integer m(Integer x) { 719 | return x * 2; 720 | } 721 | }), xs); 722 | } 723 | 724 | static int countNs(List xs, final int n) { 725 | return List.length(List.filter((new Pred() { 726 | public boolean m(Integer x) { 727 | return x == n; 728 | } 729 | }), xs)); 730 | } 731 | } 732 | ``` 733 | - In procedural with explicit environment arguments. In C, a function pointer is only a code pointer. A common technique: always define function pointers and higher-order functions to take an extra explicit environment argument. But without generics, no good choice for type of list elements or the environment. Use `void*` and various type casts... 734 | ```c 735 | typedef struct List list_t; 736 | 737 | struct List 738 | { 739 | void *head; 740 | list_t *tail; 741 | }; 742 | 743 | list_t *makelist(void *x, list_t *xs) 744 | { 745 | list_t *ans = (list_t *)malloc(sizeof(list_t)); 746 | ans->head = x; 747 | ans->tail = xs; 748 | return ans; 749 | } 750 | 751 | list_t *map(void *(*f)(void *, void *), void *env, list_t *xs) 752 | { 753 | if (xs == NULL) 754 | return NULL; 755 | return makelist(f(env, xs->head), map(f, env, xs->tail)); 756 | } 757 | 758 | list_t *filter(bool (*f)(void *, void *), void *env, list_t *xs) 759 | { 760 | if (xs == NULL) 761 | return NULL; 762 | if (f(env, xs->head)) 763 | return makelist(xs->head, filter(f, env, xs->tail)); 764 | return filter(f, env, xs->tail); 765 | } 766 | 767 | int length(list_t *xs) 768 | { 769 | int ans = 0; 770 | while (xs != NULL) 771 | { 772 | ++ans; 773 | xs = xs->tail; 774 | } 775 | return ans; 776 | } 777 | 778 | void *doubleInt(void *ignore, void *i) 779 | { 780 | return (void *)(((intptr_t)i) * 2); 781 | } 782 | 783 | // assumes list holds intptr_t fileds 784 | list_t *doubleAll(list_t *xs) 785 | { 786 | return map(doubleInt, NULL, xs); 787 | } 788 | 789 | // type casts to match what filter expects 790 | bool isN(void *n, void *i) 791 | { 792 | return ((intptr_t)n) == ((intptr_t)i); 793 | } 794 | 795 | int countNs(list_t *xs, intptr_t n) 796 | { 797 | return length(filter(isN, (void *)n, xs)); 798 | } 799 | ``` 800 | 801 | ### Mutable References 802 | 803 | 1. New types: `t ref` where `t` is a type 804 | 2. New expressions: 805 | - `ref e` to create a reference with initil contents `e` 806 | - `e1 := e2` to update contents 807 | - `!e` to retrieve contents (not negation) 808 | 3. A variable bound to a reference is still immutable: it will always refer to the same reference. But the contents of the reference may change via :=. And there may be aliases to the reference, which matters a lot. Reference are first-class values. Like a one-field mutable object, := and ! do not specify the field. 809 | 810 | ### Type Inference 811 | 812 | 1. Type inference problem: give every binding/expression a type such that type-checking succeeds. Fail if and only if no solution exists. In principle, could be a pass before the type-checker. But often implemented together. 813 | 2. Central feature of ML type inference: it can infer types with type variables - relation to polymorphism. ML is in a sweet pot because type inference is more difficult without polymorphism or with subtyping. 814 | 3. Key steps: 815 | - Determine types of bindings in order (except for mutual recursion). So you can not use later bindings: will not type-check. 816 | - For each `val` or `fun` binding: 817 | - Analyze definition for all necessary facts (constraints) 818 | - Example: if see `x > 0` then x must be type int 819 | - Type error if no way for all facts to hold (over-constrained) 820 | - Afterward, use type variables (e.g. 'a) for any unconstrained types. Example: an unused argument can have any type. 821 | - Finally, enforce the value restriction. A variable-binding can have a polymorphic type only if the expression is a variable or value. Else get a warning and unconstrained types are filled in with dummy types (basically unusable). The value restriction can cause problems when it is neccessary because we are not using mutation (Usually wrap in a function binding to fix it). 822 | 823 | ### Mutual Recursion 824 | 825 | 1. Allow f to call g and g to call f: 826 | ```sml 827 | fun f1 p1 = e1 828 | and f2 p2 = e2 829 | and f3 p3 = e3 830 | 831 | datatype t1 = ... 832 | and t2 = ... 833 | and t3 = ... 834 | ``` 835 | 2. State-machine: each state of the computation is a function. State transition is call another function with rest of input. Generalizes to any finite-state-machine example. 836 | ```sml 837 | fun match xs = 838 | let 839 | fun s_need_one xs = 840 | case xs of 841 | [] => true 842 | | 1 :: xs' => s_need_two xs' 843 | | _ => false 844 | and s_need_two xs = 845 | case xs of 846 | [] => false 847 | | 2 :: xs' => s_need_one xs' 848 | | _ => false 849 | in s_need_one xs end 850 | ``` 851 | 852 | ### Modules 853 | 854 | 1. ML has structures to define modules. `structure MyModule = struct bindings end`. This is namespace management. Can use `open ModuleName` to get direct access to a module bindings. But often better to create local val-bindings for just the bindings. 855 | 2. A signature is a type for a module (what bindings does it have and what are their types). Can define a signature and ascribe it to modules. Real value of signatures is to hide bindings and type definitions. 856 | ```sml 857 | signature MATHLIB = 858 | sig 859 | val fact : int -> int 860 | val half_pi : int 861 | end 862 | 863 | structure MyMathLib :> MATHLIB = 864 | struct 865 | fun fact x = 866 | if x = 0 867 | then 1 868 | else x * fact (x - 1) 869 | 870 | val half_pi = Math.pi / 2.0 871 | 872 | fun doubler y = y + y 873 | 874 | val eight = doubler 4 875 | end 876 | ``` 877 | 3. Modules with the same signatures still define different types. Different modules have different internal invariants. In fact, they have different type definitions. 878 | 879 | ### Equivalence 880 | 881 | 1. It is much easier to be equivalent if there are fewer possible arguments, e.g. with a type system and abstraction or avoiding side-effects: mutation, I/O, exceptions... 882 | 2. Different definitions of equivalence: 883 | - PL Eq: given same inputs, same outputs and effects. 884 | - Asymptotic Eq: ignore constant factors. 885 | - Systems Eq: Account for constant overheads, performance tune. 886 | 887 | > Note: for relevant code and more, see https://github.com/raptazure/pluw 888 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # λ Magic Books 2 | 3 | Functional Programming, Type Theory, Magical Spells... 4 | 5 | - [Agda](https://github.com/lambda-magic/plt.books/tree/master/Agda) 6 | - [Compiler](https://github.com/lambda-magic/plt.books/tree/master/Compiler) 7 | - [Coq](https://github.com/lambda-magic/plt.books/tree/master/Coq) 8 | - [Elixir](https://github.com/lambda-magic/plt.books/tree/master/Elixir) 9 | - [GC](https://github.com/lambda-magic/plt.books/tree/master/GC) 10 | - [Haskell](https://github.com/lambda-magic/plt.books/tree/master/Haskell) 11 | - [Idris](https://github.com/lambda-magic/plt.books/tree/master/Idris) 12 | - [Interpreter](https://github.com/lambda-magic/plt.books/tree/master/Interpreter) 13 | - [Lisp](https://github.com/lambda-magic/plt.books/tree/master/Lisp) 14 | - [ML](https://github.com/lambda-magic/plt.books/tree/master/ML) 15 | - [Rust](https://github.com/lambda-magic/plt.books/tree/master/Rust) 16 | - [Type Theory](https://github.com/lambda-magic/plt.books/tree/master/Type%20Theory) 17 | 18 | *Welcome to add your favourite books too :)* 19 | -------------------------------------------------------------------------------- /Rust/Programming Rust.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Rust/Programming Rust.pdf -------------------------------------------------------------------------------- /Rust/README.md: -------------------------------------------------------------------------------- 1 | ## Part1 2 | 3 | - [Understanding and Evolvingthe Rust Programming Language](https://github.com/lambda-magic/plt.books/blob/master/Rust/Understanding%20and%20Evolving%20the%20Rust%20Programming%20Language%20-%20RalfJung.pdf) 4 | 5 | ## Part2 6 | - [fp-core.rs](https://github.com/JasonShin/fp-core.rs) - A library for functional programming in Rust 7 | -------------------------------------------------------------------------------- /Rust/Rust_Crash_Course.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Rust/Rust_Crash_Course.pdf -------------------------------------------------------------------------------- /Rust/Understanding and Evolving the Rust Programming Language - RalfJung.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Rust/Understanding and Evolving the Rust Programming Language - RalfJung.pdf -------------------------------------------------------------------------------- /Rust/wrj-thesis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Rust/wrj-thesis.pdf -------------------------------------------------------------------------------- /Type Theory/2018-hott-intro-course.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/2018-hott-intro-course.pdf -------------------------------------------------------------------------------- /Type Theory/2019-summer-school.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/2019-summer-school.pdf -------------------------------------------------------------------------------- /Type Theory/Advanced topics in types and programming languages.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/Advanced topics in types and programming languages.pdf -------------------------------------------------------------------------------- /Type Theory/Benjamin_C._Pierce-Types_and_Programming_Languages-The_MIT_Press(2002).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/Benjamin_C._Pierce-Types_and_Programming_Languages-The_MIT_Press(2002).pdf -------------------------------------------------------------------------------- /Type Theory/DependentTypesAtWork.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/DependentTypesAtWork.pdf -------------------------------------------------------------------------------- /Type Theory/HoTT-UF-Agda.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/HoTT-UF-Agda.pdf -------------------------------------------------------------------------------- /Type Theory/Homotopy-Type-Theory-Univalent-Foundations-of-Mathematics.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/Homotopy-Type-Theory-Univalent-Foundations-of-Mathematics.pdf -------------------------------------------------------------------------------- /Type Theory/Languages_as_Libraries.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/Languages_as_Libraries.pdf -------------------------------------------------------------------------------- /Type Theory/README.md: -------------------------------------------------------------------------------- 1 | ## [15-819 (Homotopy Type Theory)](http://www.cs.cmu.edu/~rwh/courses/hott/) Lecture Notes 2 | 3 | [https://github.com/RobertHarper/hott-notes](https://github.com/RobertHarper/hott-notes) 4 | 5 | Per-commit PDFs can be downloaded from [GitHub Actions](https://github.com/RobertHarper/hott-notes/actions). See the [detailed instructions for downloading artifacts](https://docs.github.com/en/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts#downloading-or-deleting-artifacts) 6 | -------------------------------------------------------------------------------- /Type Theory/Type Theory and Formal Proof .pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/Type Theory and Formal Proof .pdf -------------------------------------------------------------------------------- /Type Theory/Types and Programming Languages.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/Types and Programming Languages.pdf -------------------------------------------------------------------------------- /Type Theory/cubicalmethods.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/cubicalmethods.pdf -------------------------------------------------------------------------------- /Type Theory/gradual_type_theory.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/gradual_type_theory.pdf -------------------------------------------------------------------------------- /Type Theory/hott-intro.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/hott-intro.pdf -------------------------------------------------------------------------------- /Type Theory/hott-online-1272-ga50f9bd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/hott-online-1272-ga50f9bd.pdf -------------------------------------------------------------------------------- /Type Theory/impldtp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/impldtp.pdf -------------------------------------------------------------------------------- /Type Theory/practical_foundations_for_pl.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/practical_foundations_for_pl.pdf -------------------------------------------------------------------------------- /Type Theory/propositions-as-types.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/propositions-as-types.pdf -------------------------------------------------------------------------------- /Type Theory/quantitative-type-theory.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/quantitative-type-theory.pdf -------------------------------------------------------------------------------- /Type Theory/ttfp.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/ttfp.pdf -------------------------------------------------------------------------------- /Type Theory/typesystems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/Type Theory/typesystems.pdf -------------------------------------------------------------------------------- /notanum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lambda-magic/plt-books/10c80c7550ad3a08d46c4330c42b67d1f6ce57ff/notanum.pdf --------------------------------------------------------------------------------