Possible and Partial Solution to Building Streams in C

Illustrating the concepts of Heap and collateral processing
and how hard these things are to construct in a typical language like C

Other solutions might be more elegant - this one just illustrates the point
Limitations: stream tokens are integers only; only some Cons calls are supported.

#include < stdio.h >
#include < stdlib.h >

typedef struct stream {
  struct stream *(*f)(const int); //Pointer to a function
  ...
  int first;
  int arg1;
  ...
} STREAM;

int First(STREAM *s) //Function which shows the first token of a stream
{
  return s->first;
}

STREAM *Rest(STREAM *s) //Function which invokes a producer for next token
{
  if (s->f != NULL) return (s->f)(s->arg1); //This is how to invoke a function from a pointer
  ...
  else
  return NULL;
}

STREAM *Cons(int first, STREAM *(*f)(int), int token) //Function which suspends a producer
{
  STREAM *o;

  o = (STREAM *)malloc(sizeof(STREAM));
  ...
  o->arg1 = token;
  o->f = f;
  ...
  return o;
}

int IsEmpty(STREAM *s)
{
  if (s == NULL) return 1;
  return 0;
}

STREAM *Succ(int n)
{
  return Cons(n, Succ, n+1);
}

STREAM *Fib(int n, int x, int y) //Fibonnaci Number Producer
{
  ...
}

STREAM *Finite(int n)
{
  if (n < 0) return NULL;
  return Cons(n, Finite, n-1);
}

STREAM *Times(int token, STREAM *s)
{
  if (s == NULL) return NULL;
  return ConsA(First(s)*token, Times, token, Rest(s));
}

STREAM *Merge(STREAM *s1, STREAM *s2)
{
  ...
}

int main() //Examples of the use of above functions - you determine outcome
{
  STREAM *s;
  int n;

  printf("<%d>",First(Succ(1)));
  printf("<%d>",First(Rest(Succ(1))));
  printf("<%d>",First(Rest(Rest(Succ(1)))));
  printf("<%d><%d>",First(Rest(Succ(1))),First(Rest(Rest(Succ(1)))));
  printf("\n");

  printf("<%d>",First(Times(3, Succ(1))));
  printf("<%d>",First(Rest(Times(3, Succ(1)))));
  printf("<%d>",First(Rest(Rest(Times(3, Succ(1))))));
  printf("<%d>",First(Rest(Rest(Rest(Times(3, Succ(1)))))));
  printf("\n");

  printf("<%d>",First(Times(4, Succ(1))));
  printf("<%d>",First(Rest(Times(4, Succ(1)))));
  printf("<%d>",First(Rest(Rest(Times(4, Succ(1))))));
  printf("<%d>",First(Rest(Rest(Rest(Times(4, Succ(1)))))));
  printf("\n");

  printf("<%d>",First(Times(4, Times(4, Succ(1)))));
  printf("<%d>",First(Rest(Times(4, Times(4, Succ(1))))));
  printf("<%d>",First(Rest(Rest(Times(4, Times(4, Succ(1)))))));
  printf("\n");

  printf("<%d>",First(Fib(1,1,1)));
  printf("<%d>",First(Rest(Fib(1,1,1))));
  printf("<%d>",First(Rest(Rest(Fib(1,1,1)))));
  printf("<%d>",First(Rest(Rest(Rest(Fib(1,1,1))))));
  printf("<%d>",First(Rest(Rest(Rest(Rest(Fib(1,1,1)))))));
  printf("\n");

  for (s = Finite(10) ; !IsEmpty(s) ; s = Rest(s)) printf("<%d>",First(s));
  printf("\n");

  for (s = Times(4,Finite(10)) ; !IsEmpty(s) ; s = Rest(s)) printf("<%d>",First(s));
  printf("\n");

  for (s = Merge(Times(3,Succ(1)), Fib(1,1,1)), n=0 ; n < 20 ; n++, s = Rest(s))
     printf("<%d>",First(s));
  printf("\n");

  for (s = Primes(0) ; !IsEmpty(s) ; s = Rest(s)) printf("<%d>",First(s));
  printf("\n");

  return 0;
}