summaryrefslogtreecommitdiff
path: root/notes/haskell.md
diff options
context:
space:
mode:
Diffstat (limited to 'notes/haskell.md')
-rw-r--r--notes/haskell.md118
1 files changed, 118 insertions, 0 deletions
diff --git a/notes/haskell.md b/notes/haskell.md
new file mode 100644
index 0000000..a810a0e
--- /dev/null
+++ b/notes/haskell.md
@@ -0,0 +1,118 @@
+---
+title: haskell
+published: 2024-09-12T23:42:45+0100
+---
+
+## Static typing, pure functions, and lazy evaluation
+
+I use GHC2010 with a number of extra extensions, so code on this card may not be compliant with Haskell2010.
+
+## Index
+- [Generic types]
+- [Abstractions]
+ - [Semigroup]
+ - [Monoid: A Semigroup with an identity element]
+ - [Functor: A computation whose values can be mapped over]
+ - [Applicative: A functor with expression embedding and sequencing]
+ - [Monad: An applicative functor that can be flattened]
+- [Out]
+
+# Generic types
+Haskell has *parametric polymorphism*, meaning a function or datatype can handle multiple input types.
+```hs
+-- Polymorphic function with type variable `a'
+id ∷ a → a
+id x = x
+
+-- Also works with datatypes
+data Tree = Leaf | Node a (Tree a) (Tree a)
+```
+
+# Abstractions
+Haskell includes a lot of useful abstractions, some of which draw from **category theory**, a branch of maths. This might sound scary if you're unfamiliar, but you don't need to know category theory to know the language. These abstractions can be extremely useful, and without them, purely functional programming would be a pain in the ass!!
+
+## Semigroup
+An abstract representation of an object that has 1 associative binary operation. Yeah, that is it!
+```hs
+class Semigroup m where
+ (<>) ∷ m → m → m
+```
+
+Laws:
+```hs
+x <> (y <> z) == (x <> y) <> z
+```
+
+## Monoid: A semigroup with an identity element
+```hs
+class Semigroup m ⇒ Monoid m where
+ mempty ∷ m -- Identity element
+ mappend ∷ m → m → m -- Synonym for `<>'
+```
+
+Laws:
+```hs
+x <> mempty == x
+mempty <> x == x
+```
+
+## Functor: A computation whose values can be mapped over
+The functor **f β** is made from **f α** by transforming all of its values **(α → β)** while leaving the structure **f** itself unmodified.
+```hs
+class Functor f where
+ fmap ∷ (a → b) → f a → f b
+```
+
+Laws:
+```hs
+fmap id == id
+fmap (f . g) x == fmap f (fmap f x)
+```
+
+Extra methods:
+```hs
+(<$>) = fmap
+(<$) ∷ a → f b → f a
+($>) ∷ f a → b → f b
+void ∷ f a → f ()
+```
+
+## Applicative: A functor with expression embedding and sequencing
+```hs
+class Functor m ⇒ Applicative f where
+ (<*>) ∷ f (a → b) → f a → f b -- Sequencing
+ pure ∷ a → f a -- Expression embedding
+```
+
+Laws:
+```hs
+fmap f x == pure f <*> x
+
+pure id <*> v == x
+pure (.) <*> u <*> v <*> w == u <*> (v <*> w)
+u <*> pure y == pure ($ y) <*> u
+```
+
+## Monad: An applicative functor that can be flattened
+'>>=' could be named 'flatMap', as it's the equivelant of mapping **m α → m (m β)** and then flattening **m (m β) → m β**.
+
+```hs
+class Applicative m ⇒ Monad m where
+ (>>=) ∷ m a → (a → m b) → m b -- Flat map
+ (>>) ∷ m a → m b → m b -- Sequence and discard
+ return ∷ a → m a -- Synonym for `pure'
+```
+
+Laws:
+```hs
+pure a >>= f == f a
+m >>= pure == m
+(m >>= f) >>= g == m >>= (\x → f x >>= g)
+```
+
+# Out
+:::::{.links}
+- [mooc.fi's free online Haskell course](https://haskell.mooc.fi/)
+- [haskellbyexample](https://lotz84.github.io/haskellbyexample/)
+- [module organization guidelines for haskell projects](https://www.haskellforall.com/2021/05/module-organization-guidelines-for.html)
+:::::