Я столкнулся с несколькими ситуациями, когда мне нужен список:
[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] -- no (0,0)
Обратите внимание, что в списке нет (0,0). Я использую кортежи (dx, dy) для поиска вверх, вниз, влево, вправо и по диагонали от координаты.
Каждый раз, когда я пишу его, я чувствую, что должен быть более сжатый и/или более простой способ прочитать его. Я относительно новичок в Haskell, и я фигурирую где-то в сумке с аппликативными /Functor/Monad трюками, должен быть аккуратный способ сделать это.
Я пробовал:
[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
Иногда лучше просто написать это, но я не думаю, что это один из тех времен. Это не очевидно, если взглянуть, что (0,0) не входит в комплект, и вы должны немного прочитать его, чтобы заметить шаблон.
map (\[a,b] -> (a,b)) $ delete [0,0] $ sequence $ replicate 2 [-1,0,1]
Мне нравится выше, потому что я получаю там "2", что является хорошим явным способом сказать "мы делаем то же самое в два раза", но я не могу принять карту впереди с большой небезопасной лямбдой и двумя именами.
[(dx,dy) | let a = [-1,0,1], dx <- a, dy <- a, (dx,dy) /= (0, 0)]
У этого слишком много имен в нем, но использует понимание списка точно так, как оно было разработано. Это может быть проще читать для тех, кто действительно любит списки, но мне не нравятся все имена.
let x = [-1,0,1] in delete (0,0) $ (,) <$> x <*> x
Это выглядит красивее imo, но у меня нет этого "2", и у меня есть имя. Это мой любимый пока, но он не чувствует себя прекрасно.
Я думаю, что если бы я понял, как лучше писать, я мог бы глубже понять Функторы/Монады или тому подобное. Я читал о них совсем немного, и я слышал кучу слов, таких как fmap/mconcat/etc, но я не знаю, в какую из них можно было бы справиться в этой ситуации.