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