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