#haskell #cartesian-product #cartesian-coordinates
#haskell #декартово произведение #декартовы координаты
Вопрос:
Итак, я пишу функцию allCoords
, которая возвращает список всех возможных координат в сетке ширины w
и высоты h
width
и height
должна быть неотрицательными целыми числами, чтобы вернуть разумный результат.
Пример: allCoords 3 2
должен возвращать [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]
Это все, что у меня есть на данный момент, но я не знаю, как даже начать писать функцию
type GridCoord = (Int, Int)
allCoords :: Int -> Int -> [GridCoord]
Комментарии:
1. изменения не должны приводить к аннулированию существующих ответов. если у вас уже «есть это», то в чем будет вопрос?
Ответ №1:
Вы могли бы сделать это, используя понимание списка.
[ (x,y) | x <- [0..1], y <- [0..2] ]
Даст список в вашем примере.
Затем ваша функция должна быть определена как:
type GridCoord = (Int, Int)
allCoords :: Int -> Int -> [GridCoord]
allCoords height width = [ (x,y) | x <- [0..width-1], y <- [0..height-1] ]
Ответ №2:
range
Функция делает это.
import Data.Ix
allCoords h w = range ((0,0), (w,h))
Ответ №3:
Мы можем использовать Functor
и Applicative
экземпляр списка для генерации этого с помощью:
allCoords :: (Num a, Enum a, Num b, Enum b) => a -> b -> [(a, b)]
allCoords h w = (,) <$> [0 .. h-1] <*> [0 .. w-1]
Здесь (,) <$> [0 .. h-1]
будет создан список функций b -> (a, b)
, в которых первый элемент кортежа уже заполнен. При TupleSection
включенном s этот список эквивалентен [(0,), (1,), …, (w-1,)]
.
Затем (<*>)
функция будет принимать функцию из этого списка и для каждой такой функции вызывать ее для каждого значения в списке [0 .. w-1]
, создавая таким образом 2-кортежа.
Например:
Prelude> allCoords 3 4
[(0,0),(0,1),(0,2),(0,3),(1,0),(1,1),(1,2),(1,3),(2,0),(2,1),(2,2),(2,3)]