Creating a list from 1 to 10 is simple using range notation:
[1..10] -- [1,2,3,4,5,6,7,8,9,10]
To specify a step, add a comma and the next element after the start element:
[1,3..10] -- [1,3,5,7,9]
Note that Haskell always takes the step as the arithmetic difference between terms, and that you cannot specify more than the first two elements and the upper bound:
[1,3,5..10] -- error
[1,3,9..20] -- error
To generate a range in descending order, always specify the negative step:
[5..1] -- []
[5,4..1] -- [5,4,3,2,1]
Because Haskell is non-strict, the elements of the list are evaluated only if they are needed, which allows us to use infinite lists. [1..]
is an infinite list starting from 1. This list can be bound to a variable or passed as a function argument:
take 5 [1..] -- returns [1,2,3,4,5] even though [1..] is infinite
Be careful when using ranges with floating-point values, because it accepts spill-overs up to half-delta, to fend off rounding issues:
[1.0,1.5..2.4] -- [1.0,1.5,2.0,2.5] , though 2.5 > 2.4
[1.0,1.1..1.2] -- [1.0,1.1,1.2000000000000002] , though 1.2000000000000002 > 1.2
Ranges work not just with numbers but with any type that implements Enum
typeclass. Given some enumerable variables a
, b
, c
, the range syntax is equivalent to calling these Enum
methods:
[a..] == enumFrom a
[a..c] == enumFromTo a c
[a,b..] == enumFromThen a b
[a,b..c] == enumFromThenTo a b c
For example, with Bool
it's
[False ..] -- [False,True]
Notice the space after False
, to prevent this to be parsed as a module name qualification (i.e. False..
would be parsed as .
from a module False
).