Writing a counter function

John Hughes rjmh@cs.chalmers.se
Sat, 29 Jun 2002 19:53:17 +0200 (MET DST)


On Sat, 29 Jun 2002, Shlomi Fish wrote:
>
> No. But I want to generate an irregular series, which I determine the
> intervals between two consecutive numbers myself. E.g:
>
> let (num1, next1) = (counter 5)
>     (num2, next2) = (next1 100)
>     (num3, next3) = (next2 50) in
>     [num1,num2,num3]
>
> Will have the numbers [5, 105, 155].
>

The other answers you've received really question whether this is a good
way to use Haskell at all --- usually, if you want to generate a sequence
of values, it's a good idea just to represent them explicitly as a (lazy)
list. For example, you can compute more-or-less the same result as you
want just using standard list processing functions:

Main> scanl (+) 0 [5,100,50]
[0,5,105,155]

However, you can also do almost exactly what you suggest. Not quite
exactly, because the function you describe would have a recursive type

type Counter = Int -> (Int, Counter)

and Haskell requires that type recursion involve a data or newtype. So,
here's a solution:

newtype Counter = Counter (Int -> (Int, Counter))

count :: Counter -> Int -> (Int, Counter)
count (Counter c) = c

counter n = (n, Counter next)
  where next k = counter (n+k)

xs = let (num1, next1) = (counter 5)
         (num2, next2) = (next1 `count` 100)
         (num3, next3) = (next2 `count` 50) in
       [num1,num2,num3]

Main> xs
[5,105,155]

The only difference from your idea is that a counter is not a function; we
have to use the function count to invoke it. And that's forced on us by
the need to avoid type recursion.

John Hughes