Haskell - 在元组内操作数据

Dev*_*Dev 1 haskell tuples

我正试图用haskell来模拟一个跳棋游戏.我得到一个名为checkersState的4元组,我想用几个不同的函数来操作.到目前为止,我有一个函数oneMove,它接收来自checkerState的输入,并应返回修改数据的元组:

输入元组:

    (
    3600,
    "",
    [
    "----------",
    "------r---",
    "----------",
    "----------",
    "---r-r----",
    "------r---",
    "---w---w-w",
    "----------",
    "----------",
    "------w---"
    ],
    (
    49
    ,
    43  
    )
    )
Run Code Online (Sandbox Code Playgroud)

到目前为止,我有类似于下面定义我的函数的东西但不确定如何访问元组checkerState中的各个成员.这种方法需要一段时间,一系列被捕获的棋子,棋盘和移动制作,并返回一个时间,一系列被捕获的棋子和棋盘.目前,我想根据主板的状态修改元组中的时间(INT):

    onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])
Run Code Online (Sandbox Code Playgroud)

提前致谢!

ick*_*fay 7

您可以使用模式匹配来提取元素,执行需要进行的任何更改,并将它们打包回元组.例如,如果要增加第一个值,则可以:

onemove (a,b,c,d) = (a + 1,b,c,d)
Run Code Online (Sandbox Code Playgroud)

如果你发现自己做了很多,你可能会重新考虑使用元组而不是使用数据类型:

data CheckersState = CheckersState { time  :: Int       -- field names are just
                                   , steps :: [Char]    -- guesses; change them
                                   , board :: [[Char]]  -- to something that
                                   , pos   :: (Int, Int)  -- makes sense
                                   } deriving (Eq, Read, Show)
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用更方便的语法更新它:

onemove state = state { time = time state + 1 }
Run Code Online (Sandbox Code Playgroud)

如果你想坚持使用元组并且碰巧使用镜头,那么还有另一种更新元组的简单方法:

onemove = over _1 (+1)
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用镜头您自己的数据类型(使用适当定义的访问器,如提供的那个),您可以执行类似的操作:

_time :: Lens' CheckersState Int
_time f state = (\newTime -> state { time = newTime }) <$> f (time state)

onemove = over _time (+1)
Run Code Online (Sandbox Code Playgroud)

所以有很多奇特的方法可以做到这一点.但最常用的方法是使用模式匹配.