Difference between revisions of "99 questions/Solutions/22"

From HaskellWiki
Jump to navigation Jump to search
m (This edit provides another method of computing the range without using reverse)
(another scanl example)
 
(3 intermediate revisions by 3 users not shown)
Line 26: Line 26:
 
| n < m = n:(range (n+1) m)
 
| n < m = n:(range (n+1) m)
 
| n > m = n:(range (n-1) m)
 
| n > m = n:(range (n-1) m)
  +
</haskell>
  +
or, a generic and shorter version of the above
  +
<haskell>
  +
range :: (Ord a, Enum a) => a -> a -> [a]
  +
range a b | (a == b) = [a]
  +
range a b = a:range ((if a < b then succ else pred) a) b
  +
</haskell>
  +
or with scanl
  +
<haskell>
  +
range l r = scanl (+) l (replicate (l - r) 1)
  +
</haskell>
  +
with support for both directions
  +
<haskell>
  +
range l r = scanl op l $ replicate diff 1
  +
where
  +
op = if l < r then (+) else (-)
  +
diff = abs $ l - r
 
</haskell>
 
</haskell>
   
 
Since there's already syntactic sugar for ranges, there's usually no reason to define a function like 'range' in Haskell. In fact, the syntactic sugar is implemented using the enumFromTo function, which is exactly what 'range' should be.
 
Since there's already syntactic sugar for ranges, there's usually no reason to define a function like 'range' in Haskell. In fact, the syntactic sugar is implemented using the enumFromTo function, which is exactly what 'range' should be.
  +
  +
  +
[[Category:Programming exercise spoilers]]

Latest revision as of 02:08, 5 April 2014

Create a list containing all integers within a given range.

range x y = [x..y]

or

range = enumFromTo

or

range x y = take (y-x+1) $ iterate (+1) x

or

range start stop
    | start > stop  = reverse (range stop start)
    | start == stop = [stop]
    | start < stop  = start:range (start+1) stop

The following does the same but without using a reverse function

range :: Int -> Int -> [Int]
range n m
    | n == m = [n]
    | n < m = n:(range (n+1) m)
    | n > m = n:(range (n-1) m)

or, a generic and shorter version of the above

range :: (Ord a, Enum a) => a -> a -> [a]
range a b | (a == b) = [a]
range a b = a:range ((if a < b then succ else pred) a) b

or with scanl

range l r = scanl (+) l (replicate (l - r) 1)

with support for both directions

range l r = scanl op l $ replicate diff 1
  where
  op = if l < r then (+) else (-)
  diff = abs $ l - r

Since there's already syntactic sugar for ranges, there's usually no reason to define a function like 'range' in Haskell. In fact, the syntactic sugar is implemented using the enumFromTo function, which is exactly what 'range' should be.