I have this simple code:
module Matrix where
matrix :: a -> (Int, Int) -> [[a]]
matrix x (width, height) = replicate height (replicate width x)
mapMatrix :: (a -> b) -> [[a]] -> [[b]]
mapMatrix f m = map (map f) m
When I do:
mapMatrix (+1) (matrix 0 (2,2))
I get, as expected:
[[1,1],[1,1]]
Probably I'm misunderstanding monads and/or the >>=
operator but I was expecting the following to have the same output:
matrix 0 (2,2) >>= mapMatrix (+1)
Instead I get:
Non type-variable argument in the constraint: Num [b] (Use FlexibleContexts to permit this) When checking the inferred type It :: forall b. (Num [b], Num b) => [[b]]
How can I write mapMatrix (+1) (matrix 0 (2,2))
with monads, so I can read and write the code from left-to-right instead of in-to-out because as you can imagine, I'm planning on using mapMatrix
a lot on the same matrix, something like:
matrix ... >>= mapMatrix ... >>= mapMatrix .. >>= ...
This not what a monad is supposed to do. You are likely interested in (&) :: a -> (a -> b)
defined in Data.Function
.
matrix ... & mapMatrix ... & mapMatrix .. & ...
Note that the signature of bind is
(>>=) :: m a -> (a -> m b) -> m b
and one cannot simply ignore the m
s.
For completeness, note that one actually can make bind behave almost the way you want it to using one particular monad: Identity
. It takes a bit of wrapping/unwrapping the constructor though.
module Matrix where
import Data.Functor.Identity
matrix :: a -> (Int, Int) -> Identity [[a]]
matrix x (width, height) = Identity $ replicate height (replicate width x)
mapMatrix :: (a -> b) -> [[a]] -> Identity [[b]]
mapMatrix f m = Identity $ map (map f) m
Then, the following works too:
runIdentity (matrix ... >>= mapMatrix ... >>= mapMatrix .. >>= ...)
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