example definition program theorem

The list monad encodes nondeterminism (many-worlds: return all results at once):

instance Monad [] where
  as >>= k = concat (fmap k as)      -- join = concat
  return a = [a]                     -- determinism is trivial nondeterminism

Nested loops of imperative languages become binds: as aggregates the inner loop, k is the outer loop body. Thanks to laziness a Haskell list behaves like an iterator/generator.

Sources: DaoFP §14.1 (“Nondeterminism”), §14.4, §14.5 (pairs), §15.3 (“Free monoid and the list monad”), §14.8 (“the list monad is not free because its join irreversibly smashes the lists together”), §14.9 (the two Applicative instances: cartesian and zip); Kittenlab Lecture 7 (Free-Forgetful Adjunction); 7 Sketches §5.2.4; CTfS Example 5.3.2.2, Example 4.3.1.8, Exercise 4.3.1.9

From the free monoid adjunction (Monads from Adjunctions, Free Monoid): between and ; sends to the singleton [x] (return); the counit is the monoid morphism foldMap id = foldr mappend mempty, one direction of ; whiskering, instantiates at the free monoid ([], (++)), giving join = foldr (++) [] = concat.

  • The monad laws on an example (CTfS Example 5.3.2.2): flattens ; the unit laws say that flattening or gives back , and associativity that flattening inside-first or outside-first both give . Flattening and singletons are natural transformations and (CTfS Example 4.3.1.8).
  • pairs as bs = do { a <- as; b <- bs; return (a, b) } enumerates all pairs (Do Notation, DaoFP Exercise 14.5.2).
  • Two Applicative Functor structures: the monadic one applies every function to every argument; the zip one (pure = repeat, fs <*> as = zipWith ($) fs as) is applicative but not a monad (DaoFP Exercise 14.9.3). The Monoidal instance is the cartesian product of lists (DaoFP Exercise 14.9.1).

Docs: Kittenlab Lecture 7

ret(a) = [a]
bind(as, k) = reduce(vcat, (k(a) for a in as); init=Any[])   # concat ∘ map
pairs(as, bs) = bind(as, a -> bind(bs, b -> ret((a, b))))
pairs(1:2, 'a':'b')                    # [(1,'a'), (1,'b'), (2,'a'), (2,'b')]
# Catlab/Kittenlab: the free monoid on a set is the list monoid, μ = concat
import Mathlib
#check @List.bind            -- l.bind f = (l.map f).join
#check @List.join
#check @List.singleton       -- return; Lean's List is an instance of Monad
example : List (ℕ × Char) := do let a ← [1, 2]; let b ← ['a', 'b']; pure (a, b)
pairs :: [a] -> [b] -> [(a, b)]
pairs as bs = do
  a <- as
  b <- bs
  return (a, b)
 
epsilon :: Monoid m => [m] -> m          -- the counit of F ⊣ U
epsilon = foldr mappend mempty
joinL :: [[a]] -> [a]
joinL = foldr (++) []                    -- = concat