Haskell's Composable Splitting Combinators

For prior art it might be worth looking at Haskell’s split library, and in particular its nice set of composable splitting combinators. There’s probably some way to turn this into a nice Rebol dialect, though this is something I haven’t really thought about before.

1 Like

Actually… you know what, now that I think of it, isn’t PARSE a perfectly good Rebol-native substitute for these sorts of combinators? And of course it’s more flexible too.

Splitting with PARSE is possible (Rebol SPLIT generates parse rules):

>> parse "your words here" [
       collect try some further keep between <here> [space | <end>]
   ]
== ["your" "words" "here"]

Using the default behavior, seems at minimum you'd need the COLLECT and KEEP combinators...gets wordy. (Note: Not the same as the lambda-based COLLECT and KEEP... needs to handle "rollback" on failed rules.)

So it seems to be its own domain... though maybe it could use the UPARSE engine just with a different combinator set and an implicit COLLECT. Definitely worth taking a look at.

But.. lots of other things in the air right now to consider, so I just wanted to put a pin in it... :pushpin: I've ignored SPLIT for a decade now, it can wait a little longer :slight_smile:

1 Like

Since we’re talking about Haskell here, I’ll mention that this feels a lot like composition of monad transformers, where the order of composition determines the rollback behaviour you get. Specifically, a ParsecT Void Text (Writer [a]) will rollback the list on failure, whereas a WriterT [a] (Parsec Void Text) will accumulate results from all parsing branches. The order in which you execute your side-effects determines which ones get ‘prioritised’, so to speak.

Of course, Rebol can’t do this, since it doesn’t do systematic tracking of side-effects. What’s more, in this regard dialects are almost anti-compositional, since they provide no standardised mechanism to do this kind of hooking-in. Thus, if you want to extend a dialect with side-effecting operations, you’re forced to individually work out the interaction of each side-effecting operation with the dialectal operations, as you did in that link.

Hmm… now that I’m thinking along these lines, could rebinding be Rebol’s answer to Haskell monads? For instance, COLLECT gives its supplied block the extra ability to KEEP values… just like the Writer monad allows its code to tell values to a log. Similarly, FUNC gives its body the ability to RETURN early, similarly to how Cont allows its code to callCC an early return.

In which case, it may be possible to use rebinding as a mechanism of combining side-effects. Could there be some kind of standardised mechanism for importing these kinds of rebinds into dialects? I don’t know, and in any case this speculation has drifted rather far off-topic, but it’s an interesting idea to consider.

1 Like