递归函数的“无所事事”保护?

时间:2015-12-29 13:18:57

标签: haskell recursion

我们有以下功能来构建一棵树。 它是一棵树,它有一个Node和你想要的多个子树。

INSERT INTO #Results ( . . . )
   SELECT . . .
   FROM WarehouseMgmt.DimTime DT LEFT JOIN
        WarehouseMgmt.FactPaymentAgr Aggr
        ON DT.Id = Aggr.TimeId AND [PlayerId] = @PlayerID
   WHERE (CalendarWeekId BETWEEN @CurrentWeek7 AND @CurrentWeek) 
   GROUP BY PlayerId, CalendarWeekID

现在的问题是找到一个递归的基本情况。 我们有一个名为identifyWinner的函数,它可以完成它所说的内容。

这个想法是,使用这个函数来确定某人是否赢了,并在发生时停止制作子树。但这看起来像这样:

generateGameTree g p = Node (g,p) [ ((fst x),generateGameTree (snd x) (nextPlayer p))  | x <- (findPossibleMoves p g) ]

我们无法弄清楚如何实际做任何事情。 有没有办法在Haskell中实现这一点?

提前致谢!

3 个答案:

答案 0 :(得分:3)

首先,它是 un-Haskell 来说Haskell做了一些事情,这是声明性编程和懒惰编程的全部要点。您描述输出。实际生成方式取决于编译器。

要回答您的问题,您可以稍微更改一下您的功能,以便它允许Maybe

generateGameTree g p = 
    | identifyWinner g p == Nothing = Just $ Node (g,p) $ filter (isJust . snd) [ ((fst x),generateGameTree (snd x) (nextPlayer p))  | x <- (findPossibleMoves p g) ]
    | otherwise = Nothing

filter将过滤掉树中的Nothing

另一个(或多或少等价的)解决方案是生成节点列表,列表为空或单例:

generateGameTree g p = 
    | identifyWinner g p == Nothing = [Node (g,p) $ concat [ ((fst x),generateGameTree (snd x) (nextPlayer p))  | x <- (findPossibleMoves p g) ] ]
    | otherwise = []

答案 1 :(得分:1)

如果你有一个功能

nextPositions :: Game -> [Game]

给出了在给定位置采取所有可能移动可能产生的所有位置,然后游戏树是来自Control.Comonad.CofreeCofree [] Game

type GameTree = Cofree [] Game

可以使用

生成
generateGameTree :: Game -> GameTree
generateGameTree = coiter nextPositions

如果获胜的位置没有下一个位置,那么该代将自动停在获胜位置。如果需要,您可以将其转换为更常见的Data.Tree表示。

答案 2 :(得分:0)

如果已经有胜利者,这意味着游戏已经结束并且没有更多动作,那么结果应该是什么,游戏的当前状态以及没有孩子的列表,所以:

makeGameTree g p =
  | identifyWinner g p == Nothing =
    Node (g,p) [ (fst x, makeGameTree (snd x) (nextPlayer p))
               | x <- (findPossibleMoves p g) ]
  | otherwise = Node (g,p) []