Are there any interesting one-shot monograms besides Maybe and Aither?

In the Monte programming language, as well as in its ancestor E , there is a syntax for one-time bounded continuations called "ejectors", which are continuations that are effectively used only once within a syntactic boundary. For example, here's an unnamed ejector called:

escape ej { 42 }

      

And the ejector that is called:

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

      

Both are evaluated before 42

. We can also attach an action to the case when the ejector is called:

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

      

What about all this syntax. It is not hard to imagine how this imitates Maybe

or Either

. I'll write an example from the Haskell Wiki on Maybe in an 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 carry the burden of passing ej

. Monte lacks a "programmable semicolon" do-notation.)

I won't do it Either

, but it's pretty much the same; the ability to add a sentence catch

provides the required type discrimination. Delimited continuations are well known, so you can create complex tools:

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

      

These gadgets are used in Monte to create handwritten parser combinators, for example. So, in "The Mother of All Monads, " Dan Piponi explains that Cont

in a certain sense it is very primal Monad

upon which many others can be built Monad

. We can try to do this in Monte too. Let's use the Moggi style to encode monads in object 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 code the binding helper i

to see what it looks like:

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

      

... This is not useful. This doesn't sound 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 be cool robots, not this. However, there is another problem; let encode other 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 make a traditional Cartesian product. First, let's do a straight forward calculation; instead of passing in 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 the 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! This is pretty interesting. A full computation of the list monad is performed, but the ejector only sees the first item in the list. I suspect that since ejectors are composite, there is a way to build a more complex boolean monad that does a better job of not calculating as many intermediate results.

So my question is this: when we convert Maybe

and Either

to idiomatic Monte, we can clearly see that the ejector syntax is applied elegantly. What other monads are out there that have interesting one-shot behavior? Don't be limited to Haskell; Monte is untyped, so no one will avoid you for hard monads!

+3


source to share





All Articles