Okay so have you ever heard about the interpretation of IO in Haskell being akin to a State monad, with a magic value that represents the real world being threaded through? So e.g. putStrLn "Hello, world." :: IO () can be thought of as a function that takes the world as input, and outputs a new world in which “Hello, world.” has been printed to stdout.

(Spoilers: if you look at the output of ghc -ddump-simpl, that happens to be how GHC implements it under the hood… but don’t let that spoil it for you. It’s not the only valid interpretation, it just happens to be one that’s used in one popular compiler.)

Mercury makes this explicit. So in Mercury, you might write io.write_string("Hello, world.", inworld, outworld), where inworld has type io::di, which means “a world, which will be destroyed by this function”, and outworld has type io::uo, which means “a new world, which is unique and may be destroyed at most once”. (The notation !IO you see in examples is syntactic sugar for threading a state variable called IO through.)

This made me fall off my chair laughing the first time I tried it in action.

I don’t do Haskell. So, my guess is that 0x2ba22e11 is illustrating the difference between one with syntactic sugar and one which forces you to unnecessarily deal with low-level details. The humor may come from the fact that the language claims to learn from Haskell but turns a simple thing in Haskell into a verbose mess of syntax. This one example of the Mercury folks shooting themselves in the foot vs Haskell might imply things about other design decisions they made. This is just my guess.

You see the blue arrows? Those are data dependencies, where the real world is threaded through. The black edges are the normal data dependencies, for example in the first image an Add operation takes two parameters. Later a Call operation also takes two parameters, but it also takes the world and returns a new world.

All compilers have to track this for all languages. In this representation C is just as “functional” or “monadic” as Haskell or Mercury. However, most compilers track this implicitly.

That’s what most say. It’s not easy to integrate different paradigms in programming. It was first done by LISP then to a degree other languages with functional bent. They’ll have a Prolog DSL or something. It’s unusual to see it done the other way where authors give Haskell or OCaml-like features to a logic language. So, I posted it in case people want to experiment with it.

I’m also eyeballing it as a target for executable specifications in conjunction with high-assurance systems or a verified theorem prover like Milawa. Idea being to map Mercury operations to Milawa’s stack, create a modification to Mercury to produce a trace for a program execution, and run the trace through the verified checker. From there, the verified program can be a reference against an efficient, imperative one or a verified compiler/interpreter/runtime can be used to distribute the Mercury program itself if not hurting performance or something like that. The automated solvers used in things like SPARK can already handle quite a bit of that logic.

Oh, I did not know that Mercury is still alive. I always dismissed it as historical research language. So today I read the wikipedia page for the first time and it seems it is actually used commercially.