繁体   English   中英

Haskell-在元组中处理数据

[英]Haskell--Manipulating data within a tuple

我正在尝试使用haskell模拟跳棋游戏。 我得到了一个名为checkersState的4元组,我想使用几个不同的函数进行操作。 到目前为止,我有一个函数oneMove,它从checkerState接收输入,并应返回修改后的数据的元组:

输入元组:

    (
    3600,
    "",
    [
    "----------",
    "------r---",
    "----------",
    "----------",
    "---r-r----",
    "------r---",
    "---w---w-w",
    "----------",
    "----------",
    "------w---"
    ],
    (
    49
    ,
    43  
    )
    )

到目前为止,我有一些类似于下面定义我的函数的内容,但是不确定如何访问元组checkerState中的各个成员。 此方法将花费时间,捕获的棋子阵列,木板,然后进行制造,然后返回时间,捕获的棋子阵列和木板。 目前,我想根据板卡的状态修改元组中的时间(INT):

    onemove :: (Int,[Char],[[Char]],(Int,Int)) -> (Int,[Char],[[Char]])

提前致谢!

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

onemove (a,b,c,d) = (a + 1,b,c,d)

如果发现自己经常这样做,则可以重新考虑使用元组,而改为使用数据类型:

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)

然后,您可以使用更方便的语法对其进行更新:

onemove state = state { time = time state + 1 }

如果要坚持使用元组,而碰巧在使用lens ,则有另一种简单的方法来更新元组:

onemove = over _1 (+1)

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

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

onemove = over _time (+1)

因此,有很多不错的方法可以做到这一点。 但是最通用的方法是使用模式匹配。

正如icktoofay所说,使用元组是一种代码味道,而使用命名组件进行记录则更好。

另外,使用Char(和String)是一种代码味道。 要对其进行修复,请定义一种数据类型,该数据类型应准确描述您希望在电路板上某个单元格中看到的内容,例如data Colour = None | Red | Black data Colour = None | Red | Black data Colour = None | Red | Black ,但请参阅下一项。

而且,使用列表也是一种代码味道。 您实际上想要的是类似type Board = Data.Map.Map Pos ColourData.Map.Map Pos (Maybe Colour')data Colour' = Red | Black data Colour' = Red | Black

哦,而且Int也是代码的味道。 您可以定义新类型newtype Row = Row Int ; newtype Col = Col Int ; type Pos = (Row,Col) newtype Row = Row Int ; newtype Col = Col Int ; type Pos = (Row,Col) newtype Row = Row Int ; newtype Col = Col Int ; type Pos = (Row,Col) 可能为新类型deriving Num ,但尚不清楚,例如,您不想乘以行号。 也许deriving (Eq,Ord,Enum)就足够了,使用Enum可以得到predsucc

(啊,这个Pos使用的是一个元组,因此它很臭吗?嗯,不可以,有时允许2个元组。)

您可以使用模式匹配将元组分解为变量。

onemove (i, c, board, (x, y)) = <do something> (i, c, board)

但是,您应该为董事会定义一个单独的数据结构,以明确您的意图。 我不知道前两个值的含义。 参见: http : //learnyouahaskell.com/making-our-own-types-and-typeclasses

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM