So I am writing a function allCoords
that returns a list of every possible coordinate in a grid of width w
and height h
Both width
and height
must be non-negative integers in order to return a sensible result.
Example: allCoords 3 2
should return [(0,0),(0,1),(0,2),(1,0),(1,1),(1,2)]
This is all I've got so far but I don't know how to even start writing the function
type GridCoord = (Int, Int)
allCoords :: Int -> Int -> [GridCoord]
You could do that using a list comprehension.
[ (x,y) | x <- [0..1], y <- [0..2] ]
Will give the list in your example.
Your function would then need to be defined as:
type GridCoord = (Int, Int)
allCoords :: Int -> Int -> [GridCoord]
allCoords height width = [ (x,y) | x <- [0..width-1], y <- [0..height-1] ]
The range
function does that.
import Data.Ix
allCoords h w = range ((0,0), (w,h))
We can make use of the Functor
and Applicative
instance of a list to generate this with:
allCoords :: (Num a, Enum a, Num b, Enum b) => a -> b -> [(a, b)]
allCoords h w = (,) <$> [0 .. h-1] <*> [0 .. w-1]
Here (,) <$> [0 .. h-1]
will produce a list of functions b -> (a, b)
where the first item of the tuple is already filled in. With the TupleSection
s enabled, this list is equivalent to [(0,), (1,), …, (w-1,)]
.
Then the (<*>)
function will take a function from this list, and for each such function call it on each value in the list [0 .. w-1]
, thus constructing 2-tuples.
For example:
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)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With