Haskell Language Ranges


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).