Understanding `sequence` with `[[a]]` Monad - haskell

Given:
Prelude>[ [Just 10, Just 20], [Just 5] ]
[ [Just 10, Just 20], [Just 5] ]
it has type:
Prelude> :t [ [Just 10, Just 20], [Just 5] ]
[ [Just 10, Just 20], [Just 5] ] :: Num a => [[Maybe a]]
I'd like to apply this to sequence:
Prelude> :t sequence
sequence :: Monad m => [m a] -> m [a]
The Monad m in the above List is: [a], as I understand, so I'd expect the types to line up as:
sequence :: Monad m => [m a] -> m [a]
[[a]] -> [[a]]
Assuming that's right, then please help me understand the output:
Prelude> sequence [ [Just 10, Just 20], [Just 5] ]
[[Just 10,Just 5],[Just 20,Just 5]]

It might be easier to do this with just Ints instead of Maybe Ints:
> sequence [[10, 20], [5]]
[[10,5],[20,5]]
it :: [[Int]]
The type signature you deduced is correct, it does have type [[a]] -> [[a]] in this situation, where a ~ Int in my example or a ~ Maybe Int in your example. Whenever using sequence in the list monad, I like to think of it as an N-dimensional Cartesian product. It desugars to something like
sequence [a, b, c] = do
x <- a
y <- b
z <- c
return [x, y, z]
But with an arbitrary number of elements, not just 3. Some other examples might help explain:
sequence [["a1", "a2", "a3"], ["b1", "b2"], ["c1", "c2", "c3"]]
[
["a1","b1","c1"],["a1","b1","c2"],["a1","b1","c3"],["a1","b2","c1"],["a1","b2","c2"],["a1","b2","c3"],
["a2","b1","c1"],["a2","b1","c2"],["a2","b1","c3"],["a2","b2","c1"],["a2","b2","c2"],["a2","b2","c3"],
["a3","b1","c1"],["a3","b1","c2"],["a3","b1","c3"],["a3","b2","c1"],["a3","b2","c2"],["a3","b2","c3"]
]
If you study this output closely, you'll see that we have each element of the as matched with each element of the bs and each element from the cs. Since there are 3 as, 2 bs, and 3 cs, there are 3*2*3 == 18 elements in the output.

What sequence does is to turn something like
[foo, bar, baz]
into something like
do
x <- foo
y <- bar
z <- baz
return [x, y, z]
In your case, we have
do
x <- [Just 10, Just 5]
y <- [Just 5]
return [x, y]
which is the same as
foreach x in [Just 10, Just 5]
foreach y in [Just 5]
return [x, y]
in psuedo-OO syntax.
It should now be fairly obvious why you get the result you do.

Related

Haskell - How the construct do calls fail function from Monad?

While studying Monads I understood why when pattern matching on list definitions fails, its computation is somewhat "ignored" instead of throwing an error:
test :: [(Int, Int)]
test = [(x, y) | (Just x) <- [Just 1, Nothing, Just 3], y <- [1, 2]]
*Main> test
[(1,1),(1,2),(3,1),(3,2)]
It's because it is just a syntactic sugar for a Monad application using do:
test'' :: [(Int, Int)]
test'' = do
(Just x) <- [Just 1, Nothing, Just 3]
y <- [1, 2]
return (x, y)
*Main> test'
[(1,1),(1,2),(3,1),(3,2)]
*Main> test == test'
True
Similarly, we could try to resemble this logic using the bind operator >>=:
test'' :: [(Int, Int)]
test'' = [Just 1, Nothing, Just 3] >>= \(Just x) -> [1, 2] >>= \y -> return (x, y)
However, as expected, the monadic function fail relative to List will not be called in this situation like it was in the previous ones:
*Main> test''
[(1,1),(1,2)*** Exception: test.hs:11:40-82: Non-exhaustive patterns in lambda
So, my question is: Is it possible to get [(1,1),(1,2),(3,1),(3,2)] using test'' style, in a neat way? Is do construct a syntactic sugar for something like this?
test'' :: [(Int, Int)]
test'' = [Just 1, Nothing, Just 3] >>= \maybeX -> [1, 2] >>= \y -> case maybeX of Just x -> return (x, y)
_ -> fail undefined
*Main> test''
[(1,1),(1,2),(3,1),(3,2)]
*Main> test'' == test
True
For instance
{-# LANGUAGE LambdaCase #-}
test'' = [Just 1, Nothing, Just 3] >>= \case
Just x -> [1, 2] >>= \y -> return (x, y)
_ -> fail "..."

Converting `do notation` to >>= v. map

Given the following do notation code:
do
a <- return 1
b <- [10,20]
return $ a+b
Is there a more idiomatic conversion:
ghci> return 1 >>= (\x -> map (+x) [10, 20])
[11,21]
versus
ghci> return 1 >>= (\x -> [10, 20] >>= (\y -> [y+x]))
[11,21]
do notation maps to monadic functions, so strictly you'd write
return 1 >>= (\a -> [10, 20] >>= (\b -> return $ a+b ))
Now, you can replace that >>= … return by just fmap
return 1 >>= (\x -> fmap (\y -> x+y) [10, 20])
and use sections, and scrap that constant 1 right into the function
fmap (1+) [10, 20]
Alternatively, if you really want to take your first summand from a list, I'd recommend to use liftM2:
liftM2 (+) [1] [10, 20]
A bit more idiomatic than this, and with the same results, is the Applicative instance of lists:
(+) <$> [1] <*> [10, 20]

A simple version of Haskell's map

I'm trying to define map in ghci recursively. What I've come up with so far is the following:
let mymap f (x:xs) = if null xs then [] else f x : map f xs
What I'd like to do now is to simplify it a bit and hardcode the list inside the code, i.e., write a map function which takes a function as argument and does what the real map does but only to a specific list e.g., [1, 2, 3, 4, 5].
Is such a thing possible?
First of all, your map function isn't entirely correct. If I were to input mymap (+1) [1], I would expect to get [2] back, but instead I'd get []. If I tried mymap (+1) [], my program would crash on a pattern match failure, since you haven't defined that case. Instead, consider defining your mymap as
mymap :: (a -> b) -> [a] -> [b]
mymap f [] = []
mymap f (x:xs) = f x : mymap f xs
If you want to do it inline with an if statement then you'd have to do
mymap f xs = if null xs then [] else f (head xs) : mymap f (tail xs)
These do essentially the same thing, but the first is a bit easier to read in my opinion.
If you want to use mymap to define a function that maps only over a specific list, you could do so pretty easily as
mapOnMyList :: (Int -> b) -> [b]
mapOnMyList f = mymap f [1, 2, 3, 4, 5]
Or in point-free form
mapOnMyList = (`mymap` [1, 2, 3, 4, 5])
using mymap as an infix operator. This is equivalent to flip mymap [1, 2, 3, 4, 5], but the operator form is usually preferred since flip is not necessarily free to execute.
You can also do this using list comprehensions:
mymap f xs = [f x | x <- xs]
Or if you want to hard code the list
mapOnMyList f = [f x | x <- [1, 2, 3, 4, 5]]

Why we use a monoid and a functor there?

I'm new in Haskell.
I can't figure out why we use a monoid and instance Functor Matrix in the code bellow and how instance Functor Matrix works?
instance Functor Matrix where
fmap f (M n m v) = M n m $ fmap (fmap f) v
instance Num a => Num (Matrix a) where
fromInteger = M 1 1 . V.singleton . V.singleton . fromInteger
negate = fmap negate
(+) = add
(*) = mult
abs = fmap abs
signum = fmap signum
scalarMult :: Num a => a -> Matrix a -> Matrix a
scalarMult = fmap . (*)
I know that the functor is necessary for negate, (*), abs, signum, but I need a detailed explanation. Help me, please.
Functors are a very simple thing that have a complicated name. Simply put, Functors are containers that you can map a function over its values, via the fmap function. Lists are the most familiar Functor, since fmap is just map. Other Functors include Maybe, IO, and Either a.
In this snippet you're defining Matrix to be a Functor, so you're telling the compiler that Matrix is a container that it can map functions over. For the purposes of this question, fmap is used to define several of the functions in the Num typeclass. It is pretty easy to see how this works (assuming there is a fromList :: [[a]] -> Matrix a function):
> fmap id $ fromList [[1, 2], [3, 4]]
fromList [[1, 2], [3, 4]]
> fmap (+1) $ fromList [[1, 2], [3, 4]]
fromList [[2, 3], [4, 5]]
> fmap show $ fromList [[1, 2], [3, 4]]
fromList [["1", "2"], ["3", "4"]]
For other Functors:
> fmap (+1) [1, 2, 3]
[2, 3, 4]
> fmap (*10) (Just 1)
Just 10
> fmap (*10) Nothing
Nothing
As for why Data.Monoid is imported in the source for Data.Matrix, it is solely because of the function
-- | Display a matrix as a 'String' using the 'Show' instance of its elements.
prettyMatrix :: Show a => Matrix a -> String
prettyMatrix m#(M _ _ v) = unlines
[ "( " <> unwords (fmap (\j -> fill mx $ show $ m ! (i,j)) [1..ncols m]) <> " )" | i <- [1..nrows m] ]
where
mx = V.maximum $ fmap (V.maximum . fmap (length . show)) v
fill k str = replicate (k - length str) ' ' ++ str
Where the author has opted to use <> instead of ++ for concatenating strings together, a rather mundane use of the list Monoid. It has no relevance at all to the Matrix type.

haskell foldl with (++)

I was playing with Haskell and ghci when I found this which really bothers me:
foldl (++) [[3,4,5], [2,3,4], [2,1,1]] []
I expected to get this: [3,4,5,2,3,4,2,1,1]
However it gets:
[[3,4,5],[2,3,4],[2,1,1]]
As far as I understand foldl, it should be this:
(([] ++ [3, 4, 5]) ++ [2, 3, 4]) ++ [2, 1, 1]
If I type this in ghci it really is [3,4,5,2,3,4,2,1,1].
And the other strange thing is this:
Prelude> foldl1 (++) [[3,4,5], [2, 3, 4], [2, 1, 1]]
[3,4,5,2,3,4,2,1,1]
I expect foldl and foldl1 to behave in the same way. So what does foldl actually do?
The order of arguments is wrong. The right one is:
foldl (++) [] [[3,4,5], [2,3,4], [2,1,1]]
(That is, first the accumulator, then the list.)
You switched the arguments around. foldl takes the accumulator's starting value first, then the list to fold. So what happens in your case is that foldl folds over the empty list and thus returns the starting value, which is [[3,4,5], [2, 3, 4], [2, 1, 1]]. This will do what you want:
foldl (++) [] [[3,4,5], [2, 3, 4], [2, 1, 1]]
You got the argument order wrong
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
Prelude> :t foldl1
foldl1 :: (a -> a -> a) -> [a] -> a
The initial value comes first. In your case, your initial value was [[3,4,5],[2,3,4],[2,1,1]] and you folded over the empty list, so you got back the initial value.

Resources