Search code examples
haskelldictionaryiofunctional-programmingpurely-functional

Haskell: for each (k,v) in Map, do IO() with k and v


I have a Map (Int,Int) Charand I'm trying to draw each Chars in it at the position contained in the key. My functions are:

import qualified Data.Map.Strict as SM
data Position = Position !GLint !GLint

drawMirrors :: SM.Map (Int,Int) Char -> IO()
drawMirrors mirrors = do
    mapM_ (\(x,y) c -> drawMirror c (Position x y)) mirrors

drawMirror :: Char -> Position -> IO()
drawMirror orientation (Position x y) = do
    -- Some irrelevant stuff

At the drawMirrors mirrors = do mapM_ (\(x,y) c -> drawMirror c (Position x y)) mirrors line, I'm getting the error:

src\Main.hs:200:33:

Couldn't match expected type `Char -> IO ()'
            with actual type `IO b0'
The lambda expression `\ (x, y) c -> drawMirror c (Position y)'
has two arguments,
but its type `(t0, GLint) -> IO b0' has only one
In the first argument of `mapM_', namely
  `(\ (x, y) c -> drawMirror c (Position y))'
In a stmt of a 'do' block:
  mapM_ (\ (x, y) c -> drawMirror c (Position y)) mirrors

How can I, in drawMirrors, get all the keys and values in the dictionary and apply the drawMirror function with these keys and values?


Solution

  • Your lambda, \(x,y) c -> drawMirror c (Position x y), takes two arguments. However, it is called with a single argument of the form (key, value) (in your case ((x, y), c).

    (\((x,y), c) -> drawMirror c (Position x y))
    

    Moreover, mapM_ (which I believe in your case is from Data.Foldable) only iterate over the keys, so you might want to call SM.toList to have a list of (key, value).

    The final result is :

    drawMirrors :: SM.Map (Int,Int) Char -> IO()
    drawMirrors mirrors = do
        mapM_ (\((x,y), c) -> drawMirror c (Position x y)) $ SM.toList mirrors