Ranges and enumeration
| Ranges | |
| Step sizes | |
| Infinite ranges | |
| repeat, cycle, replicate |
Ranges
Two dots between two values of an enumerable type produce the list of everything in between. The upper bound is included:
[1..5] -- [1,2,3,4,5]
['a'..'e'] -- "abcde"
[1.0,1.5..3.0] -- [1.0,1.5,2.0,2.5,3.0]
A range needs an Enum instance, which numbers, characters, and booleans have. It works because the type knows how to walk from one value to the next.
Step sizes
Give two starting values and the range continues with the same difference. The third value is the upper bound, not the step:
[0,2..10] -- [0,2,4,6,8,10]
[10,8..0] -- [10,8,6,4,2,0]
[1,4..20] -- [1,4,7,10,13,16,19]
A step that never reaches the bound produces a short list rather than an error: [1,3..10] ends at 9. A descending range with a positive step is empty, which is the usual cause of a function that silently returns nothing.
Infinite ranges
Leave the upper bound out and the list never ends. Because Haskell is lazy, nothing is computed until a consumer asks:
take 5 [1..] -- [1,2,3,4,5]
take 4 [0,5..] -- [0,5,10,15]
takeWhile (< 100) (map (^2) [1..])
-- [1,4,9,16,25,36,49,64,81]
take and takeWhile are the two standard ways to cut an infinite list down to size. A bare infinite range printed at the prompt runs until you press Ctrl+C.
repeat, cycle, replicate
Three generators cover the cases that a range cannot express. repeat never stops, cycle loops a finite list, and replicate counts:
take 3 (repeat 7) -- [7,7,7]
take 5 (cycle [1,2]) -- [1,2,1,2,1]
replicate 3 "ha" -- ["ha","ha","ha"]
concat (replicate 3 "ha") builds a string
from repeated pieces, which is the usual reason to reach for
replicate.
Next:
List comprehensions
Article author: Arthur Isaev