Personal tools

99 questions/Solutions/22

From HaskellWiki

< 99 questions | Solutions(Difference between revisions)
Jump to: navigation, search
(slightly modified the version with guards so that it will make backwards ranges too)
(another scanl example)
 
(4 intermediate revisions by 4 users not shown)
Line 18: Line 18:
 
| start == stop = [stop]
 
| start == stop = [stop]
 
| start < stop = start:range (start+1) stop
 
| start < stop = start:range (start+1) stop
  +
</haskell>
  +
The following does the same but without using a reverse function
  +
<haskell>
  +
range :: Int -> Int -> [Int]
  +
range n m
  +
| n == m = [n]
  +
| 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.