[Haskell-cafe] Using streams to clarify (?) the signature of Data.Text.replace

MarLinn monkleyon at googlemail.com
Mon Jun 27 23:00:14 UTC 2016

>     > Imagine a generalized version of replace that 1) works on
>     streams, and
>     >      replace' :: Stream (Stream (Of Text) m) m ()
>     >                  -> Stream (Stream (Of Text) m) m Void
>     >                  -> Stream (Of Text) m r
>     >                  -> Stream (Of Text) m r
>     >
>     >
>     > Do you find easy to intuit, just by looking at that signature, which
>     > is the function of each argument?
>     Absolutely not.  In fact, this crossed my personal complexity horizon
>     and is still accelerating towards some kind of singularity.
I agree 100%. What is going on here?
If you just wanted to clarify the signature, why not just use type synonyms?

     type Replaced = Text
     type Replacement = Text

     replace :: Replaced -> Replacement -> Text -> Text

No breaking changes necessary. You don't even have to export the synonyms.
Or generalize the function in a much simpler fashion:

     replace :: (Text -> Text) -> Text -> Text

There should be no ambiguity here. It's less powerful than the 
stream-monster because the argument function is stateless - but then 
whatever kind of stream you use probably has some zipWith function that 
you could use for more complicated cases.

> A possible use case: you want to "splice" the contents of a sequence 
> of files into another file at certain words, without having to keep 
> whole files in memory, and without using lazy I/O.

I'm not really familiar with streams or pipes, but that does sound like 
a perfect use case for conduits. Still, I'm at a loss how that thing 
would look internally. How do you "find" a stream of Text in another 
Text? What does that even mean, semantically? So if I understand the use 
case correctly, you have some "trigger words" in a Text and want to 
replace each trigger with the contents of a file, as in a templating 
system. The simplest type I could come up with for that would be

       replace' :: Map Text (Stream (Of Text) m ())
                   -> Stream (Of Text) m r
                   -> Stream (Of Text) m r

Note: No Stream on the left side of an arrow. No Stream of triggers, so 
ordering is not important anymore. It wasn't helpful anyway. Easily 
generalized to non-text stuff. And as such it may already be part of 
some streaming libraries. Which is exactly as it should be: streaming 
functions should be part of streaming libraries, not a text library.

More information about the Haskell-Cafe mailing list