Ad
  • Default User Avatar

    I think it can be solved by making non-terminating coroutines polymorphic in their return type, similar to how forever itself is defined:

    filterC :: (v -> Bool) -> Coroutine r v v void
    duplicate :: Coroutine r v v void
    add :: Coroutine r Int Int void
    

    In that case, the functions could be used with consume by substituting void ~ (); and at the same time, the fact that they never return is both signalled (by similarity with functions like forever and throwIO) and enforced by the type system (as GHC won't allow to stick any non-bottom value into a now rigid type variable void).
    At least, that's what I did with my solution, and it seems to have worked.