无法将递归案例转换为Haskell

时间:2019-02-16 15:51:50

标签: python dictionary haskell

我有以下python代码:

def win(start, adjList):
  if len(adjList[start]) == 0: return True

  else:

    for vertex in adjList[startingPoint]:

      adjListCopy = copy.deepcopy(adjList)
      adjListCopy[start].remove(vertex)

      if (win(vertex, adjListCopy)): return False

  return True

这里adjList是字典,类似于{0: [1,2], 2: [3], 3: []},而start是要查看的索引,在这种情况下,假设start是0。如果我们从0开始,那么如果我们赢了,它将返回。

在haskell中,我将字典表示为Map

到目前为止,这是我的代码:

win adjList start =
    if (adjListAtstarting) == Just [] || (adjListAtstarting) == Nothing
        then True
    else
        False
        -- loop through each item in the map, and recurse

    where adjListAtstarting = Map.lookup start adjList

在haskell中的递归情况下,我需要帮助。我知道我可以使用adjListCopy[start].remove(vertex)函数执行Map.adjustWithKey。我遇到麻烦的主要原因是因为for循环。

1 个答案:

答案 0 :(得分:1)

这应该有效:

import qualified Data.Map as Map

win adjList start = not $ any f adjListAtstarting
    where adjListAtstarting = Map.findWithDefault [] start adjList
          f vertex = win (Map.adjust (filter (vertex /=)) start adjList) vertex

由于您无论如何都要处理Just []Nothing,因此我使用findWithDefault而不是lookup,因此您不必处理{{1 }}。正如AChampion指出的那样,您不需要进行Maybe测试,因为如果列表为空,则自动发生正确的事情。

ifnot $ any f adjListAtstarting的每个元素上调用函数f,如果对adjListAtstarting的所有调用都返回了{{1},则返回True },但如果对f的任何调用返回了False,则返回False。这与您的Python for循环匹配,如果内部测试曾经是f,则它立即返回True,如果由于内部测试始终为false而退出循环,则返回False

True获取一个列表,并返回一个列表,其中包含True以外的所有元素。 (注意:您在Python中使用了filter (vertex /=),这只会从列表中删除第一次出现的元素。这将从列表中删除所有匹配的元素。如果列表永远不会包含两个相同的元素,则如果这样做,那么您将需要使用the delete function (imported from Data.List)。)

vertexremove的{​​{1}}元素上调用Map.adjust (filter (vertex /=)) start adjList,并返回一个映射,其中该调用的结果是filter (vertex /=)元素的替换在输入中,其他所有元素都相同。 (您只需要start而不是adjList,因为您对值所做的更改不依赖于键。)