3

In the Monte programming language, as well as in its ancestor E, there is syntax for single-shot delimited continuations, called "ejectors," which are continuations that are effectively only usable once within a syntactic boundary. For example, here is an ejector that is not called:

escape ej { 42 }

And an ejector that is called:

escape ej { ej(42); "After 10,000 years, I'm free!" }

Both evaluate to 42. We can also attach an action to the case where the ejector is called:

escape ej { ej(2) } catch result { result + 4 }

That's about all of this syntax. It's not hard to imagine how this mimics Maybe or Either. I'll transcribe the example from the Haskell Wiki on Maybe into idiomatic Monte:

def f(x, ej):
    return if (x == 0) { ej() } else { x }

def g(x, ej):
    return if (x == 100) { ej() } else { x }

def h(x, ej):
    return g(f(x, ej), ej)

# Monte permits Unicode identifiers but not for free.
def ::"h´"(x, ej):
    def n := f(x, ej)
    return g(n, ej)

(Note how we must bear the burden of passing ej. Monte lacks the "programmable semicolon" of do-notation.)

I won't do Either, but it's largely the same; the ability to add a catch clause provides the required type discrimination. Delimited continuations are well-known to compose, so it's possible to build complex tools:

def trying(f, g, ej):
    return escape innerEj { f(innerEj) } catch _ { g(ej) }

These kinds of gadgets are used in Monte to build hand-written parser combinators, for example. So, in The Mother of all Monads, Dan Piponi explains that Cont is, in a certain sense, a very primal Monad upon which many other Monads can be built. We can attempt to do this in Monte, too. Let's use Moggi's style for encoding monads in object-based languages:

object identity:
    to unit(x):
        return x

    # "bind" is a Monte keyword; we may still use it, but not for free.
    # NB this is `x >>= f` in Haskell.
    to "bind"(x, f):
        return f(x)

And let's encode the binding helper i, to get an idea of what it looks like:

def i(m, x, ej):
    return m."bind"(x, ej)

...This isn't helpful. This isn't looking like good syntax.

# Haskell: runIdentity $ do { x <- return 32; return $ x // 4 }
escape ej { i(identity, i(identity, identity.unit(32), fn x { identity.unit(x // 4) }), ej) }

The future was supposed to have cool robots, not this. There's another problem, though; let's encode another traditional Monad, List:

object list:
    to unit(x) { return [x] }

    to "bind"(action, f):
        var rv := []
        for x in (action) { rv += f(x) }
        return rv

And let's do a traditional Cartesian product. First, let's do a direct computation; instead of passing a continuation, we'll just bind directly using the list monad:

▲> i(list, [1, 2, 3], fn x { i(list, [4, 5, 6], fn y { [x * y] }) })
Result: [4, 5, 6, 8, 10, 12, 12, 15, 18]

And now with an ejector:

▲> escape ej { i(list, i(list, [1, 2, 3], fn x { i(list, [4, 5, 6], fn y { [x * y] }) }), ej) }
Result: 4

So! That's pretty interesting. The complete list monad computation is being run, but the ejector only sees the first item in the list. I suspect that, since ejectors are composable, there's a way to build a more sophisticated logic monad which does a better job of not computing so many intermediate results.

My question, then, is this: When we transform Maybe and Either into idiomatic Monte, we can clearly see that ejector syntax applies elegantly. What other monads are out there which would have interesting single-shot behavior like this? Don't feel limited to Haskell; Monte is untyped, so nobody will shun you for hard-to-type monads!

Corbin
  • 1,530
  • 1
  • 9
  • 19
  • 2
    I doubt the idea of a “hard-to-type monad” makes sense. If it doesn't clearly unify types before and after sequencing-composition, it's not really a monad. – leftaroundabout Jun 03 '17 at 23:43
  • 1
    I was admittedly thinking about corner cases like `Cont`, which only admits a delimited `callCC` operation in Haskell's type system but for which Scheme (and Monte, via experiments, as of this morning) is perfectly happy to allow an undelimited variant. – Corbin Jun 03 '17 at 23:45

0 Answers0