2015-08-16 3 views
2

Я пытаюсь реализовать массив как список списков в Haskell. В частности, у меня есть некоторый массив m, который мне предоставлен, и предикат p, который я хочу быть удовлетворен, и я хочу создать список индексов (x,y), так что x-й элемент y-го списка удовлетворяет p. Я поставил это в качестве следующего списка понимания:Двойное представление списка в Haskell

[(x,y) | x<-[1..],y<-[1..],p ((m !! y) !! x)] 

Который бросает ошибку, когда он пытается найти элемент m в первом ряду, который не существует. Я вижу, что один из возможных способов исправить это - просто изменить внутренние соображения на x и y на что-то вроде y<-[1..length m], но я чувствую, что есть легкий способ, который использует лень. Я просто не знаю, что это.

ответ

5

Действительно есть. Распространенный идиом для получения списка элементов вместе с их индексами является использование zip:

[(x,y) | (x,mx) <- zip [1..] m, (y,mxy) <- zip [1..] mx, p mxy] 

также:

  • !! весьма неэффективен, особенно при извлечении много элементов из списка, так что лучше попробовать чтобы избежать этого, когда это возможно.
  • Индексы индексов обычно начинаются с 0 в Haskell.
+0

Aha! Я не знал, что «!!» был особенно неэффективен, спасибо за это. –

+4

@ DanielLittlewood Имейте в виду, что списки Haskell ** связаны ** структурами. Операция 'xs !! Чтобы получить элемент, n' требует перехода для ссылок 'n'. Это контрастирует с обычной индексацией массивов на самых императивных языках, поскольку для этого потребовались бы операции O (1). – Bakuriu