Элементы сетки списка

#list #haskell #element #variable-assignment

#Список #haskell #элемент #переменная-назначение

Вопрос:

Мне удалось добиться некоторого прогресса в этой части моего задания, но я приложил часть кода ниже, который я сделал:

 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)]
  

Как показано в последней строке чуть выше, мне удалось заставить update работать при 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 списка.

Заранее спасибо.

Комментарии:

1. Возможно, вам будет понятнее, если вы определите data Grid = [Row] , что эквивалентно data Grid = [[State]]

Ответ №1:

 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
  

Помните, что a Grid — это просто список Row элементов.

Вторая строка теперь означает «если вы хотите обновить 0-ю строку этой сетки, затем обновите первую строку», последняя строка должна означать «если вы хотите обновить y-ю строку этой сетки, затем оставьте первую как есть и рекурсивно обновите остальные строки» (конечно, y должен быть соответствующим образом изменен в рекурсивном вызове).

Ответ №2:

Вот решение. После некоторых размышлений я пришел к следующему и заполнил последнюю строку вышеупомянутого «шаблона»:

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