如何在一个函数中对变量进行多次测试并获得多个结果?

时间:2013-12-25 17:04:46

标签: xml haskell functional-programming

我正在使用游戏板,按坐标映射碎片。对于此示例,请考虑坐标(0,0)上方向为“N”的块“B”。我的坐标显示在一对String中,所以我的类型Piece的格式是(String,String,(String,String))

所以我希望我的脚本能够决定撤回作品的下一步行动。例如,片“E”。为此,我有4个函数来测试片段“B”周围的方块是否为空。对于这个例子,我们只考虑其中的两个。

minusx :: Piece -> [Piece] -> Bool
minusx _ [] = False
minusx (a,b,(x,y)) ((w,v,(x1,y1)):ts) = let xm = show (rInt x-1)
                                    in if (xm == x1 && y == y1 ) then True
                                       else minusx (a,b,(x,y)) ts

minusy :: Piece -> [Piece] -> Bool
minusy _ [] = False
minusy (a,b,(x,y)) ((w,v,(x1,y1)):ts) = let ym = show (rInt y-1)
                                    in if (x == x1 && ym == y1 ) then True
                                       else minusx (a,b,(x,y)) ts

因此,如果我们在(0,0)上考虑片段“B”,如果棋盘中没有任何棋子(-1,0),则减号返回false,如果没有任何棋子则减去零在(0,-1)。

如果它们是空的,则另一个功能根据撤回件和“B”件的方向制作可能的游戏列表。让我们举一个我们将用于两者的简单示例。

possibleplay :: Piece -> WithdrawPiece -> [Piece]    
possibleplay ("B","N",(x,y)) "E" = [("E","N",(x-1,y-1)),("E","S",(x-1,y-1))]

让我们想象一下,对于那里的不同功能,它可以被称为可能的游戏,只是为了得到更简单的例子。

因此,如果我们在片段(“B”,“N”,(0,0))上为取出片段“E”运行mayplayX,我们可以用两种不同的方式播放它。 (“E”,“N”,(x-1,y-1))和(“E”,“S”,(x-1,y-1)) 同样适用于可能的游戏。如果我们连续两个,我们会重复播放,但我没有不同的坐标,所以不要记住这一点。

现在这就是我被卡住的地方。我想列出所有方向的所有可能性。

我可以用if做一个接一个。

if minusx == False then possibleplayX bla bla bla

但是我想为周围的所有位置做这个。想象一下,减号和减号都是空的。如果minusx == False的结果然后运行possibleplayX,如果minusy == False运行可能的播放。如果它们都是空的,我知道如何一个接一个地但不能同时做到这一点。我怎样才能同时运行并结束所有结果?

考虑到减号可能是空的,但可能不是。

感谢您抽空帮助。 :)

编辑:刚编辑了使用类型的函数,以便更容易

type Piece = (String,String,(String,String))
type WithdrawPiece = String

1 个答案:

答案 0 :(得分:1)

所以我试着理解你的问题并编写了以下希望等效的haskell代码。

  • 但首先请考虑@alternative和@molbdnilo的建议: AVOID字符串,字符串是“便宜的”data声明,有可能在运行时输入错字,所以你可以避免编译器的帮助( - 这有点像使用C恕我直言)

所以我会宣布像

这样的东西
data PieceType = A|B|C|Empty deriving (Eq)
data Direction = N|E|S|W deriving (Eq)
data Piece = Piece { _name::PieceType
                   , _orientation::Direction
                   , _position::(Int,Int)}

我使用的下划线因为它允许我使用@ekmett的镜头库,当你有时间和资源时你一定要检查它

  • 接下来使用内置函数 - 你的减号函数本质上是一个手写any,如果我没错,那么在减号中有一个拼写错误(在你正在调用减号的else分支处)。 / p>

  • 第三,如果你正在使用元组箭头是你的朋友:Control.Arrow是抽象的但很有用。

    • (第一个f)(x,y)==(f x,y)
    • (第二g)(x,y)==(x,g y)
    • (f *** g)(x,y)==(f x,g y)

这是您的minusx - 函数

的翻译
minusx :: Piece -> [Piece] -> Bool
minusx p ps = any (\x -> (first (subtract 1) . _position) p == _position x) ps

但是我会使用不同的方法,因为你说你有空的问题,另外如果你想根据一些规则从列表中找到一些东西 - tadaa - filter函数所以可能的举动应该是

possibleMoves :: Piece -> [Piece] -> [Piece]
possibleMoves p = filter (\x -> (_name x /= Empty)&&(minusx' p x || minusy' p x))

minusx'函数

minusx' :: Piece -> Piece -> Bool
minusx' p q = (first (subtract 1) . _position) p == _position q