递归循环字典并删除键

时间:2016-12-30 23:11:04

标签: haskell dictionary recursion

我正在使用顶点和Data.Map尝试为Checkers游戏进行捕捉动作。我正在使用函数changeKey更新地图中的当前键和函数cMove以使捕获移动。现在,cMove获取一个顶点,一个顶点列表(带有对手的棋子)和一个包含顶点和一个bool值的地图,以指示该棋子属于哪个玩家。 cMove检查第一个顶点元组是否在地图中(以便知道板上的位置是否为空,因为计算找到了有效移动的位置)。如果是,则会调用changeKey

changeKey :: (Integer, Integer) -> (Integer, Integer) -> Map (Integer, Integer) Bool -> Map (Integer, Integer) Bool
changeKey k0 k1 myMap = case M.updateLookupWithKey (\_ _ -> Nothing) k0 myMap of
         (Nothing, _    ) -> myMap
         (Just e, myMap) -> M.insert k1 e myMap

cMove :: (Integer, Integer) -> [(Integer, Integer)] -> Map (Integer, Integer) Bool -> Map (Integer, Integer) Bool
cMove k [k1] myMap = if M.notMember (2*fst k1 - fst k, 2*snd k1 - snd k) myMap
                          then
                          changeKey k (2*fst k1 - fst k, 2*snd k1 - snd k) myMap
                          else myMap

我的问题在于,如果列表包含多个元组(因为玩家每回合可以进行无限量的捕获),我在黑暗中如何循环遍历顶点列表。此外,如何确保代表对手棋子的每个键都将从地图中删除。

1 个答案:

答案 0 :(得分:2)

首先,the documentation for Data.Map建议您在类似情况下使用Data.Map.Strict代替Data.Map

此外,函数名称通常应以小写字母开头。

有了这个,在这里进行迭代的一种简单方法是fold the elements of a list到最终结果Map。您编写了一个函数来处理一次迭代(参见下面的cMove'),然后使用类似foldrfoldl'的函数让它为您完成所有迭代。

我不确定以下内容是否为您提供了所需的行为,但这是使用foldr的初稿:

import Data.Map.Strict (Map(..))
import qualified Data.Map.Strict as M

changeKey :: (Integer, Integer) -> (Integer, Integer) -> Map (Integer, Integer) Bool -> Map (Integer, Integer) Bool
changeKey k0 k1 myMap = case M.updateLookupWithKey (\_ _ -> Nothing) k0 myMap of
         (Nothing, _    ) -> myMap
         (Just e, myMap) -> M.insert k1 e myMap

cMove :: (Integer, Integer) -> [(Integer, Integer)] -> Map (Integer, Integer) Bool -> Map (Integer, Integer) Bool
cMove k ks myMap = foldr (cMove' k) myMap ks
  where
    cMove' :: (Integer, Integer) -> (Integer, Integer) -> Map (Integer, Integer) Bool -> Map (Integer, Integer) Bool
    cMove' k k1 myMap = if M.notMember (2*fst k1 - fst k, 2*snd k1 - snd k) myMap
                              then changeKey k (2*fst k1 - fst k, 2*snd k1 - snd k) myMap
                              else myMap