Haskell:对于Map中的每个(k,v),用k和v做IO()

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

我有一个 Map (Int,Int) Char,我正在尝试在其中的键包含的位置绘制每个 Char。我的职能是:

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 函数?

您的 lambda \(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 中的每个键值对执行操作。