列出网格元素

时间:2011-05-14 04:30:40

标签: list haskell element variable-assignment

我已经设法在我的任务的这一部分取得了一些进展,但已经附上了我所做的部分代码:

module Grid where

data State = On | Off deriving (Eq, Show)


next :: State -> State
next On = Off
next Off = On

type Row = [State]
type Grid = [[State]]
type Point = (Int,Int)

initialRow      :: Int -> Row
initialRow w    = replicate w Off


updateRow :: Row -> Int -> Row
updateRow  (r:rs) x 
    | x==0        = next r:rs
    | otherwise   = r : (updateRow rs (x-1))

update :: Grid -> Point -> Grid
update [[]] (x,y)       =   [[]]
update [(g:gs)] (x,y)   =   [(updateRow (g:gs) x)]

正如上面的最后一行所示,我已经设法让更新在x = any Int时工作,如下所示(第x个元素被反转) - ghci。

*Grid> update [[Off,Off,Off,Off]] (2,0)
[[Off,Off,On,Off]]
*Grid> 

当我尝试使用多个这样的列表,或者在列表中选择某个列表来更新第x个元素时,这一切都会失败:

*Grid> update [[Off,Off,Off,Off],[Off,Off,Off,Off]] (2,0)
*** Exception: Grid.hs:(24,0)-(25,47): Non-exhaustive patterns in function update

我似乎无法在这个函数中“推广”一个公式。

我也必须遵循这种类型约定:

updateRow :: Grid -> Point -> Grid

基本上,我想做的是从这样的事情更新......

[[Off,Off,Off,Off],
 [Off,Off,Off,Off],
 [Off,Off,Off,Off],
 [Off,Off Off,Off]]

到此:

[[Off,Off,Off,Off],
 [Off,Off,**On**,Off],
 [Off,Off,Off,Off],
 [Off,Off Off,Off]]

其中'x'是元素的值,'y'是列表IYGWIM中列表的值。

提前致谢。

2 个答案:

答案 0 :(得分:2)

update :: Grid -> Point -> Grid
update [[]] (x,y)       =   [[]]

这将检查包含空列表的列表。

update [(g:gs)] (x,y)   =   [(updateRow (g:gs) x)]

这将检查包含一个列表的列表,后者包含至少一个元素(绑定到变量g)。

您想要检查包含多个列表的列表。

模式应如下所示:

update :: Grid -> Point -> Grid
update [[]] (x, y)       = [[]]
update (row:rows) (x, 0) = updateRow row x : rows
update (row:rows) (x,y)  = -- I'll let you fill this, notice the 0 on the previous line

请记住,Grid只是Row的列表。

第二行现在意味着“如果你想更新这个网格的第0行,然后更新第一行”,最后一行应该是“如果你想更新这个网格的第y行,那么就留下第一行一个原样,并递归更新其余的行“(当然,y必须在递归调用中相应地更改)。

答案 1 :(得分:0)

这是解决方案。经过一番思考后,我出现了以下内容并填写了上述“模式”的最后一行:

...
update        (g:gs)  (x,y) =  g : update gs (x,(y-1))