what intuitive meaning of join monad?
the monads-as-containers analogies make sense me, , inside these analogies join makes sense. value double-wrapped , unwrap 1 layer. know, monad not container.
how might 1 write sensible, understandable code using join in normal circumstances, when in io?
for list monad, join concat, , concatmap join . fmap. join implicitly appears in list expression uses concat or concatmap.
suppose asked find of numbers divisors of number in input list. if have divisors function:
divisors :: int -> [int] divisors n = [ d | d <- [1..n], mod n d == 0 ] you might solve problem this:
foo xs = concat $ (map divisors xs) here thinking of solving problem first mapping divisors function on of input elements , concatenating of resulting lists. might think "functional" way of solving problem.
another approch write list comprehension:
bar xs = [ d | x <- xs, d <- divisors x ] or using do-notation:
bar xs = x <- xs d <- divisors return d here might said we're thinking little more imperatively - first draw number list xs; draw divisors divisors of number , yield it.
it turns out, though, foo , bar same function.
morever, these 2 approaches same in any monad. is, monad, , appropriate monadic functions f , g:
do x <- f y <- g x same as: (join . fmap g) f return y for instance, in io monad if set f = getline , g = readfile, have:
do x <- getline y <- readfile x same as: (join . fmap readfile) getline return y the do-block more imperative way of expressing action: first read line of input; treat returned string file name, read contents of file , return result.
the equivalent join expression seems little unnatural in io-monad. shouldn't using in same way used concatmap in first example.