Hi all, I would like to reuse some streaming functions from the turtle package in the context of the servant streaming handler. Relevant references: https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Shell.html https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Prelude.html https://hackage.haskell.org/package/servant-0.20/docs/Servant-Types-SourceT.... As a simple example: Turtle.Prelude.ls function represents stream of FilePaths (directory listing of some path) ls :: FilePath -> Shell FilePath Servant streaming is based around SourceT IO a, for example: type ListFiles = "ls" :> StreamGet NewlineFraming PlainText (SourceT IO FilePath) The problem is that the streaming (Shell a) is not exactly the same as servant's (SourceT IO a). But as far as I understand, they both represent "stream of values of type 'a'". My question is: Is a generic conversion function possible? Something like: shellToSource :: forall a. Shell a -> SourceIO a shellToSource = ?? ... such that I could reuse the 'ls' and write a streaming servant handler like this: listFilesHandler :: Handler (SourceIO FilePath) listFilesHandler = pure $ shellToSource $ Turtle.Prelude.ls "somePath" Appreciate any suggestion. regards, Zoran
In short, yes I think it should be possible. But messing with Shell / Fold always feels like doing a brain teaser rather than programming. If you figure it out, I would like to hear about it. :P On Fri, 30 Jun 2023 at 21:00, Zoran Bošnjak <zoran.bosnjak@via.si> wrote:
Hi all, I would like to reuse some streaming functions from the turtle package in the context of the servant streaming handler.
Relevant references: https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Shell.html https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Prelude.html
https://hackage.haskell.org/package/servant-0.20/docs/Servant-Types-SourceT....
As a simple example:
Turtle.Prelude.ls function represents stream of FilePaths (directory listing of some path) ls :: FilePath -> Shell FilePath
Servant streaming is based around SourceT IO a, for example: type ListFiles = "ls" :> StreamGet NewlineFraming PlainText (SourceT IO FilePath)
The problem is that the streaming (Shell a) is not exactly the same as servant's (SourceT IO a). But as far as I understand, they both represent "stream of values of type 'a'". My question is: Is a generic conversion function possible? Something like:
shellToSource :: forall a. Shell a -> SourceIO a shellToSource = ??
... such that I could reuse the 'ls' and write a streaming servant handler like this:
listFilesHandler :: Handler (SourceIO FilePath) listFilesHandler = pure $ shellToSource $ Turtle.Prelude.ls "somePath"
Appreciate any suggestion.
regards, Zoran _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
I have managed to convert in one direction like this: ``` sourceToShell :: forall a. SourceIO a -> Shell a sourceToShell (S.SourceT act1) = Shell act2 where act2 :: FoldShell a r -> IO r act2 (FoldShell step begin done) = act1 (go begin) where go x = \case S.Stop -> done x S.Error e -> fail e S.Skip cont -> go x cont S.Yield val cont -> step x val >>= flip go cont S.Effect eff -> eff >>= go x ``` But in the other way (that is: shellToSource) I could not find any clean solution. I've got information from turtle's author that it's not possible directly by simple manupulation of data structures. It should however be possible by forking a new thread, write elements from Shell to some shared buffer and let StepT read from this buffer. But I have decided to re-implement some small set of turtle's functions (like 'ls') to produce SourceIO, instead of Shell, so this conversion is not needed any more. Zoran From: "Bryan Richter" <bryan@haskell.foundation> To: "Zoran Bošnjak" <zoran.bosnjak@via.si> Cc: "haskell-cafe" <haskell-cafe@haskell.org> Sent: Monday, July 10, 2023 9:19:44 AM Subject: Re: [Haskell-cafe] servant streaming question In short, yes I think it should be possible. But messing with Shell / Fold always feels like doing a brain teaser rather than programming. If you figure it out, I would like to hear about it. :P On Fri, 30 Jun 2023 at 21:00, Zoran Bošnjak < [ mailto:zoran.bosnjak@via.si | zoran.bosnjak@via.si ] > wrote: Hi all, I would like to reuse some streaming functions from the turtle package in the context of the servant streaming handler. Relevant references: [ https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Shell.html | https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Shell.html ] [ https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Prelude.html | https://hackage.haskell.org/package/turtle-1.6.1/docs/Turtle-Prelude.html ] [ https://hackage.haskell.org/package/servant-0.20/docs/Servant-Types-SourceT.... | https://hackage.haskell.org/package/servant-0.20/docs/Servant-Types-SourceT.... ] As a simple example: [ http://turtle.prelude.ls/ | Turtle.Prelude.ls ] function represents stream of FilePaths (directory listing of some path) ls :: FilePath -> Shell FilePath Servant streaming is based around SourceT IO a, for example: type ListFiles = "ls" :> StreamGet NewlineFraming PlainText (SourceT IO FilePath) The problem is that the streaming (Shell a) is not exactly the same as servant's (SourceT IO a). But as far as I understand, they both represent "stream of values of type 'a'". My question is: Is a generic conversion function possible? Something like: shellToSource :: forall a. Shell a -> SourceIO a shellToSource = ?? ... such that I could reuse the 'ls' and write a streaming servant handler like this: listFilesHandler :: Handler (SourceIO FilePath) listFilesHandler = pure $ shellToSource $ [ http://turtle.prelude.ls/ | Turtle.Prelude.ls ] "somePath" Appreciate any suggestion. regards, Zoran _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: [ http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe | http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe ] Only members subscribed via the mailman list are allowed to post.
On Mon, Jul 10, 2023 at 12:03:37PM +0000, Zoran Bošnjak wrote:
It should however be possible by forking a new thread, write elements from Shell to some shared buffer and let StepT read from this buffer.
Rather than a "shared buffer", it shouldn't be too difficult with a BoundedChan. https://hackage.haskell.org/package/BoundedChan-1.0.3.0 just write to the BoundedChan on the "Shell" side, and read from it on the "SourceT" (StepT) side. -- Viktor.
participants (3)
-
Bryan Richter -
Viktor Dukhovni -
Zoran Bošnjak