Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding types in the streaming libarary

In regards to the streaming libarary What is m in Stream (Of a) m r? How could I figure this out from the documentation (sorry, a noob here)?

I'd like to understand what the type means so that I can work out my specific problem where I'm creating a stream of requests using servant, and while trying to consume it like this:

post :: Maybe Int -> ClientM [BlogPost]
post = ...

stream :: Stream (Of (ClientM [BlogPost])) ClientM ()
stream = S.map posts $ S.each $ [Just p | p <- [1..5]]

main = do
  let url = ...
  S.print $ S.map (\x -> runClientM x url) stream

But I'm getting the following error:

• Couldn't match type ‘ClientM’ with ‘IO’
  Expected type: S.Stream (S.Of (ClientM [BlogPost])) IO ()
    Actual type: S.Stream (S.Of (ClientM [BlogPost])) ClientM ()
like image 986
zoran119 Avatar asked May 15 '18 06:05

zoran119


1 Answers

If given in isolation, the m in Stream (Of a) m r could be any type.

When considering specific functions in the module, be aware of the type constraint. For example, the yield function has this type:

yield :: Monad m => a -> Stream (Of a) m ()

Here, m is constrained to be any type that's a Monad instance. This could be IO, [] (list), Maybe, State, Reader, etc.

Another function has this type:

stdinLn :: MonadIO m => Stream (Of String) m ()

Here, m is constrained to be any type that's a MonadIO instance. The MonadIO type class is a subclass of Monad, in the sense that for a type to be a MonadIO, it must already be a Monad.

AFAICT, IO is also a MonadIO, but e.g. Maybe isn't.

Thus, some of the functions in the module are more constrained than others. The yield function is less constrained than the stdinLn function. You can use Maybe as m with yield, but not with stdinLn.

Regarding your specific problem, there's not enough information in the OP for a repro, but it looks like main uses the map function from Streaming.Prelude:

map :: Monad m => (a -> b) -> Stream (Of a) m r -> Stream (Of b) m r

Here, m must be a Monad instance. In Haskell, the main function must have the type IO (), so when using do notation, the Monad instance is inferred to be IO. The error message states that the compiler expects m to be IO.

like image 192
Mark Seemann Avatar answered Sep 21 '22 07:09

Mark Seemann