I am trying to understand the expression below. It converts the list of characters ['a','b','c']
to a list of strings ["a", "b", "c"]
liftM (:[]) "abc"
How does this happen?
The robotic monkey head operator (:[])
is just the section of the list cons (:)
and the empty list []
, i.e. (:[])
is equivalent to (\x -> x:[])
; which in turn can also be written using list syntax as (\x -> [x])
.
Rewritten this way, we have
liftM (\x -> [x]) "abc"
The string literal "abc"
is also just syntax sugar for the character list ['a', 'b', 'c']
, so we can in turn rewrite the above as
liftM (\x -> [x]) ['a', 'b', 'c']
liftM
is just fmap
from the Dark Days when Functor
wasn't a superclass of Monad
, giving
fmap (\x -> [x]) ['a', 'b', 'c']
The Functor
instance of []
sets fmap = map
, giving
map (\x -> [x]) ['a', 'b', 'c']
which reduces to
[['a'], ['b'], ['c']]
Or, going back to string notation
["a", "b", "c"]
Q.e.d.
Function liftM
turns a function which takes input and produces output to a function which takes input in some monad and produces output in the same monad. Lets look at its definition:
liftM :: Monad m => (a -> b) -> m a -> m b
liftM f mx = mx >>= \x -> return (f x)
Strings in Haskell are lists of characters (type String = [Char]
), so
"abc" = ['a', 'b', 'c'] :: [Char]
From your application compiler infers a = Char
, b = [Char]
, m a = [Char]
, m = []
. So m b = [[Char]] = [String]
. List is a monad where return x = [x]
and (>>=) = concatMap
. So if we specialize above definition we get:
liftM f mx = concatMap (\x -> [f x]) mx
And if we apply the arguments we get:
concatMap (\x -> [[x]]) ['a', 'b', 'c'] =
concat $ map (\x -> [[x]]) ['a', 'b', 'c'] =
concat $ [[['a']], [['b']], [['c']]] =
[['a'], ['b'], ['c']] =
["a", "b", "c"]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With