Learning resources
Real World Haskell Learn You a Haskell for Great Good No Nonsense Monad & Functor - The foundation of Functional Programming by César Tron-Lozai 18.S097: Programming with Categories Category Theory for Programmers
Start a new project
# in current folder
nix flake init --template "github:chessl/flake-templates#haskell"
# create a new project folder
nix flake new --template "github:chessl/flake-templates#haskell" haskell-learning
Haskell is a language with many implementations, of which two are in wide use. Hugs is an interpreter that is primarily used for teaching. For real applications, the Glasgow Haskell Compiler (GHC) is much more popular.
GHC has three main components:
ghc
is an optimizing compiler that generates fast native code.ghci
is an interactive interpreter and debugger.runghc
is a program for running Haskell programs as scripts, without needing to compile them first.Haskell is not exactly lazy, it’s non-strict: https://wiki.haskell.org/Lazy_vs._non-strict
A definition or a name is just a function which doesn’t take any parameters. i.e., a variable provides a way to give a name to an expression.
The result of applying a function may be a thunk (a deferred expression).
If you’re used to imperative programming languages, you’re likely to think of a variable as a way of identifying a memory location (or some equivalent) that can hold different values at different times. In an imperative language we can change a variable’s value at any time, so that examining the memory location repeatedly can potentially give different results each time.
[1, 2, 3]
is just syntactic sugar for1:2:3:[]
, so[1, 2, 3, ..., 100000000] ++ [4]
can be really expansive as it has to walk through the whole list on the left side.5:[1, 2, ..., 10000]
is instantaneous.Type
Int
is bounded but more efficient.Integer
is not bounded.That
it
variable is a handyghci
shortcut. It lets us use the result of the expression we just evaluated in a new expression.A side effect introduces a dependency between the global state of the system and the behaviour of a function.
Side effects are essentially invisible inputs to, or outputs from, functions. Functions without side effects are pure.
In Haskell, indentation is important: it continues an existing definition, instead of starting a new one. Don’t omit the indentation!
Many languages need to treat the logical-or operator specially so that it short circuits if its left operand evaluates to True. In Haskell, (||) is an ordinary function: non-strict evaluation builds this capability into the language.
Because the result of applying a pure function can only depend on its arguments, we can often get a strong hint of what a pure function does by simply reading its name and understanding its type signature.
Because pattern matching acts as the inverse of construction, it’s sometimes referred to as deconstruction.
indentation matters in Haskell, better always use spaces for portability.
Function application with a space is left-associative (so
f a b c
is the same as((f a) b) c)
.Object-oriented programming is bad for concurrency because it hides implementations, it hides exactly the wrong thing, making them not composiable. They hide mutation inside and data sharing(using pointers), causing data race.
Category theory is the most abstract programming language, and Haskell is a poor implementation