Skip to content

Commit 88408e4

Browse files
authored
Merge pull request #1661 from shlevy/FromSourceIO-IO
fromSourceIO: Run in IO.
2 parents e9d283a + 162712d commit 88408e4

File tree

7 files changed

+29
-15
lines changed

7 files changed

+29
-15
lines changed

changelog.d/1661

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
synopsis: Make fromSourceIO run in IO
2+
prs: #1661
3+
4+
description: {
5+
6+
Some streaming abstractions, like io-streams, require stateful
7+
initialization. Since all actual call sites of `fromSourceIO`
8+
are in a context where `IO` actions can be executed, these
9+
streaming sources can be accomodated by having letting
10+
`fromSourceIO` run in `IO`.
11+
12+
To migrate your existing `FromSourceIO` instance, simply put
13+
a `pure`/`return` in front of it.
14+
15+
}

servant-client-core/src/Servant/Client/Core/HasClient.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ instance {-# OVERLAPPABLE #-}
428428
clientWithRoute _pm Proxy req = withStreamingRequest req' $ \gres -> do
429429
let mimeUnrender' = mimeUnrender (Proxy :: Proxy ct) :: BL.ByteString -> Either String chunk
430430
framingUnrender' = framingUnrender (Proxy :: Proxy framing) mimeUnrender'
431-
return $ fromSourceIO $ framingUnrender' $ responseBody gres
431+
fromSourceIO $ framingUnrender' $ responseBody gres
432432
where
433433
req' = req
434434
{ requestAccept = fromList [contentType (Proxy :: Proxy ct)]
@@ -448,7 +448,7 @@ instance {-# OVERLAPPING #-}
448448
clientWithRoute _pm Proxy req = withStreamingRequest req' $ \gres -> do
449449
let mimeUnrender' = mimeUnrender (Proxy :: Proxy ct) :: BL.ByteString -> Either String chunk
450450
framingUnrender' = framingUnrender (Proxy :: Proxy framing) mimeUnrender'
451-
val = fromSourceIO $ framingUnrender' $ responseBody gres
451+
val <- fromSourceIO $ framingUnrender' $ responseBody gres
452452
return $ Headers
453453
{ getResponse = val
454454
, getHeadersHList = buildHeadersTo . toList $ responseHeaders gres

servant-conduit/src/Servant/Conduit.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ instance (ConduitToSourceIO m, r ~ ())
5757
toSourceIO = conduitToSourceIO
5858

5959
instance (MonadIO m, r ~ ()) => FromSourceIO o (ConduitT i o m r) where
60-
fromSourceIO src =
60+
fromSourceIO src = return $
6161
ConduitT $ \con ->
6262
PipeM $ liftIO $ S.unSourceT src $ \step ->
6363
loop con step
@@ -69,4 +69,4 @@ instance (MonadIO m, r ~ ()) => FromSourceIO o (ConduitT i o m r) where
6969
loop con (S.Effect ms) = ms >>= loop con
7070
loop con (S.Yield x s) = return (HaveOutput (PipeM (liftIO $ loop con s)) x)
7171

72-
{-# SPECIALIZE INLINE fromSourceIO :: SourceIO o -> ConduitT i o IO () #-}
72+
{-# SPECIALIZE INLINE fromSourceIO :: SourceIO o -> IO (ConduitT i o IO ()) #-}

servant-machines/src/Servant/Machines.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ instance MachineToSourceIO m => ToSourceIO o (MachineT m k o) where
3535
toSourceIO = machineToSourceIO
3636

3737
instance MonadIO m => FromSourceIO o (MachineT m k o) where
38-
fromSourceIO src = MachineT $ liftIO $ S.unSourceT src go
38+
fromSourceIO src = return $ MachineT $ liftIO $ S.unSourceT src go
3939
where
4040
go :: S.StepT IO o -> IO (Step k o (MachineT m k o))
4141
go S.Stop = return Stop
4242
go (S.Error err) = fail err
4343
go (S.Skip s) = go s
4444
go (S.Effect ms) = ms >>= go
4545
go (S.Yield x s) = return (Yield x (MachineT (liftIO (go s))))
46-
{-# SPECIALIZE INLINE fromSourceIO :: SourceIO o -> MachineT IO k o #-}
46+
{-# SPECIALIZE INLINE fromSourceIO :: SourceIO o -> IO (MachineT IO k o) #-}

servant-pipes/src/Servant/Pipes.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ instance PipesToSourceIO m => ToSourceIO a (ListT m a) where
6262
instance (MonadIO m, a' ~ X, a ~ (), b' ~ (), r ~ ())
6363
=> FromSourceIO b (Proxy a' a b' b m r)
6464
where
65-
fromSourceIO src = M $ liftIO $ S.unSourceT src (return . go) where
65+
fromSourceIO src = pure $ M $ liftIO $ S.unSourceT src (return . go) where
6666
go :: S.StepT IO b -> Proxy X () () b m ()
6767
go S.Stop = Pure ()
6868
go (S.Error err) = M (liftIO (fail err))
6969
go (S.Skip s) = go s -- drives
7070
go (S.Effect ms) = M (liftIO (fmap go ms))
7171
go (S.Yield x s) = Respond x (const (go s))
72-
{-# SPECIALIZE INLINE fromSourceIO :: SourceIO x -> Proxy X () () x IO () #-}
72+
{-# SPECIALIZE INLINE fromSourceIO :: SourceIO x -> IO (Proxy X () () x IO ()) #-}
7373

7474
instance MonadIO m => FromSourceIO a (ListT m a) where
75-
fromSourceIO = Select . fromSourceIO
75+
fromSourceIO src = Select <$> liftIO (fromSourceIO src)

servant-server/src/Servant/Server/Internal.hs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -752,18 +752,17 @@ instance
752752
route Proxy context subserver = route (Proxy :: Proxy api) context $
753753
addBodyCheck subserver ctCheck bodyCheck
754754
where
755-
ctCheck :: DelayedIO (SourceIO chunk -> a)
755+
ctCheck :: DelayedIO (SourceIO chunk -> IO a)
756756
-- TODO: do content-type check
757757
ctCheck = return fromSourceIO
758758

759-
bodyCheck :: (SourceIO chunk -> a) -> DelayedIO a
759+
bodyCheck :: (SourceIO chunk -> IO a) -> DelayedIO a
760760
bodyCheck fromRS = withRequest $ \req -> do
761761
let mimeUnrender' = mimeUnrender (Proxy :: Proxy ctype) :: BL.ByteString -> Either String chunk
762762
let framingUnrender' = framingUnrender (Proxy :: Proxy framing) mimeUnrender' :: SourceIO B.ByteString -> SourceIO chunk
763763
let body = getRequestBodyChunk req
764764
let rs = S.fromAction B.null body
765-
let rs' = fromRS $ framingUnrender' rs
766-
return rs'
765+
liftIO $ fromRS $ framingUnrender' rs
767766

768767
-- | Make sure the incoming request starts with @"/path"@, strip it and
769768
-- pass the rest of the request path to @api@.

servant/src/Servant/API/Stream.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ instance ToSourceIO a [a] where
113113
-- Pipe, etc. By implementing this class, all such streaming abstractions can
114114
-- be used directly on the client side for talking to streaming endpoints.
115115
class FromSourceIO chunk a | a -> chunk where
116-
fromSourceIO :: SourceIO chunk -> a
116+
fromSourceIO :: SourceIO chunk -> IO a
117117

118118
instance MonadIO m => FromSourceIO a (SourceT m a) where
119-
fromSourceIO = sourceFromSourceIO
119+
fromSourceIO = return . sourceFromSourceIO
120120

121121
sourceFromSourceIO :: forall m a. MonadIO m => SourceT IO a -> SourceT m a
122122
sourceFromSourceIO src =

0 commit comments

Comments
 (0)