Haskell: для каждого (k,v) в Map выполните IO() с помощью k и v

У меня есть Map (Int,Int) Charи я пытаюсь нарисовать каждый CharS в нем в положении, содержащемся в ключе. Мои функции:

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

На drawMirrors mirrors = do mapM_ (\(x,y) c -> drawMirror c (Position x y)) mirrors линия, я получаю ошибку:

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

Как я могу, в drawMirrorsполучить все ключи и значения в словаре и применить drawMirror работать с этими ключами и значениями?

2 ответа

Решение

Твоя лямбда, \(x,y) c -> drawMirror c (Position x y), принимает два аргумента. Однако он вызывается с одним аргументом вида (key, value) (в твоем случае ((x, y), c),

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

Более того, mapM_ (который я верю в вашем случае от Data.Foldable) перебирайте только ключи, так что вы можете позвонить SM.toList иметь список (key, value),

Окончательный результат:

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

Я играл с этим, и нашел один способ использовать mapM_ вместо mapWithKeyM_, В частности,

{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleInstances #-}

data UnCurry :: (* -> * -> *) -> * -> * where
  UnCurry :: f k v -> UnCurry f (k, v)

instance Foldable (UnCurry Map) where
  foldr c n (UnCurry m) = M.foldrWithKey go n m
    where
      go k a b = c (k, a) b

Теперь вы можете использовать mapM_ f (UnCurry m) выполнить действие для каждой пары ключ-значение в Map,

Другие вопросы по тегам