As we already mentioned in the Applicatives section, the underlying effect of `Lists` is support for nondeterministic computations. `Maybe` computations can return either `Nothing` or a `Just` value, while `List` computations can return zero, one or multiple values based on their length. Let's see how this is defined in the `Monad` instance of `List`:
1
2
-- return :: a -> [a]
3
return x = [x]
4
5
-- (>>=) :: [a] -> (a -> [b]) -> [b]
6
m >>= f = [y | x <- m, y <- f x]
Copied!
The bind operator in this case is defined using list comprehension. Can you define it using the functions `map` and `concat`?
The `return` method simply takes a value `x` and puts it into a `List` structure `[x]`. The `(>>=)` method for lists extracts all the values `x` from the list `m` and applies the function `f` to each of them, combining all the results in one final list. As with the `Maybe` monad, the bind operator, allows us to chain operations together with lists as well. With lists, these chaining operations will combine all output possibilities in a single result list.
Let's take a look at a simple example of chaining list operations together. Imagine we want to model mitosis, a process where a single cell divides into two identical daughter cells. First, we will create a function that will simply split a cell in two and call it mitosis:
1
mitosis :: String -> [String] -- we will represent cells with simple strings
2
mitosis = replicate 2
3
4
ghci> ["Cell"] >>= mitosis
5
["Cell", "Cell"]
Copied!
With the monadic instance of lists, we have a simple way of chaining multiple operations on lists. We can chain the result of multiple cell replications starting with one cell into one final list:
1
ghci> ["Cell"] >>= mitosis >>= mitosis >>= mitosis
2
["Cell", "Cell", "Cell", "Cell", "Cell", "Cell", "Cell", "Cell"]
Copied!
In this case, the `mitosis` function is applied to each element of the list, providing a resulting list to be passed to the subsequent functions.
The monadic instance of lists also allows us to use the do notation:
1
threeGens :: String -> [String]
2
threeGens gen0 = do
3
gen1 <- mitosis gen0
4
gen2 <- mitosis gen1
5
gen3 <- mitosis gen2
6
return gen3
7
8
ghci> threeGens "Cell"
9
["Cell", "Cell", "Cell", "Cell", "Cell", "Cell", "Cell", "Cell"]
Copied!