I am very new to Haskell. Could someone please explain why defining a list like this returns an null list
ghci> let myList = [10..1]
ghci> myList
[]
However this works correctly.
ghci> let myList = [10, 9..1]
ghci> myList
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Basically, because [10..1] is translated to enumFromTo 10 1 which itself has the semantics to create a list by taking all elements less-than 1 which result from counting upward (with step-size +1) from (including) 10.
Whereas [10, 9..1] is translated to enumFromToThen 10 9 1 which explicitly states the counting step-size as 9-10, i.e. -1 (which is hard-coded to +1 for enumFromTo)
A more accurate specification can be found in the Haskell Report (6.3.4 The Enum Class):
enumFrom :: a -> [a] -- [n..]
enumFromThen :: a -> a -> [a] -- [n,n'..]
enumFromTo :: a -> a -> [a] -- [n..m]
enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m]
For the types
IntandInteger, the enumeration functions have the following meaning:
The sequence
enumFrom e1is the list[e1,e1+1,e1+2,...].The sequence
enumFromThen e1 e2is the list[e1,e1+i,e1+2i,...], where the increment, i, is e2-e1. The increment may be zero or negative. If the increment is zero, all the list elements are the same.The sequence
enumFromTo e1 e3is the list[e1,e1+1,e1+2,...e3]. The list is empty ife1 > e3.The sequence
enumFromThenTo e1 e2 e3is the list[e1,e1+i,e1+2i,...e3], where the increment,i, ise2-e1. If the increment is positive or zero, the list terminates when the next element would be greater thane3; the list is empty ife1 > e3. If the increment is negative, the list terminates when the next element would be less thane3; the list is empty ife1 < e3.
Arithmetic sequence notation is just syntactic sugar for functions from the Enum class.
[a..] = enumFrom a
[a..b] = enumFromTo a b
[a, b..] = enumFromThen a b
[a, b..c] = enumFromThenTo a b c
As for why they weren't defined to automatically reverse, I can only speculate but here are some possible reasons:
If a and b are defined elsewhere, it would be harder to tell at a glance in which direction [a..b] would go.
It has nicer mathematical properties to reason about. You don't have to add special cases for when the sequence would be reversed.
If you want to generate a list from a to b regardless of whether a < b, you can use the following:
[a, a + (signum $ b - a)..b]
For newbies.
To make a list with all the numbers from 20 to 1, you can't just do
[20..1]
you have to specify as such:
[20,19..1]
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