There are no promises about when () -> work(c) will be called. Doing schedule(t) only schedules the task but it might not actually start for a while, so whether or not it crashes depends on whether it runs before or after c gets defined.
In your first case, c is defined immediately after schedule(t), so will usually be defined before the task actually starts, so no error occurs.
In the second case, doing some IO usually ends up switching between tasks because IO is slow - it can do some other work while the IO is happening. This means that the task actually got started before c was defined, hence the error.