Hacker News new | past | comments | ask | show | jobs | submit login
The Mercury programming language (mercurylang.org)
112 points by panic on Nov 8, 2018 | hide | past | favorite | 73 comments



We use Mercury at YesLogic to write Prince, our HTML to PDF formatter! [1]

We chose it because logic/functional languages are great for tree processing, Mercury was designed for large projects, and because in 2002 there really weren't many other options around.

Its syntax and semantics are derived from Prolog, it borrows a lot from Haskell (types, type classes), in spirit it's reminiscent of OCaml (niche, little weird) and with support for unique modes there is some interesting overlap with Rust, although this aspect of the language still needs more compiler support.

All in all, definitely worth checking out.

[1] https://www.princexml.com/


I've seen a bunch of these (HTML -> PDF). I've never seen a succinct answer to: "How is this different/better than taking <random web browser> and hitting "print", which at least on OS X will produce a nice PDF?"


Prince is pretty powerful when it comes to print-specific stuff. We care about pagination, making tables look good across page breaks, footnotes, great justification, table of contents, non-sRGB color space handling, crop marks, etc. Also having great accessibility annotations (often mandatory for government documents). These are things that web browsers are less concerned with - print-to-PDF is more of an afterthought, where as for us it's our main area of focus.


That's not even close to what you get with a good HTML -> PDF export, which can include anything from proper pagination, page margins and TOCs, to orphans handling and other such concerns.


The Synfony project use princexml to generate their documentation (including The Book) and it's phenomenally good.

https://symfony.com/doc/current/index.html#gsc.tab=0

Select offline, The book, 4.2 and it generates the book on the fly.


I'm not the guy you asked but I've been using PrinceXML to produce PDFs intended for customers of our client (e.g. invoices, terms and conditions, itineraries, etc.). Sure, we could just display the HTML and let either the customer or the sales agent press "Print to PDF" but it's not very user friendly—non-power users may not know that "print to PDF" is even an option—nor is it particularly practical for batch processing.

Full disclosure: If I'd had my way we would have used LaTeX templates to produce the PDFs but the previous developers had already implemented the HTML->PDF flow, so we just replaced the old, defunct service with Prince, which did a surprisingly good job, IMO.


>Sure, we could just display the HTML and let either the customer or the sales agent press "Print to PDF" but it's not very user friendly—non-power users may not know that "print to PDF" is even an option—nor is it particularly practical for batch processing.

It's not just that. Print to PDF for basic stuff it can be an option. For complex documents, print workflows, etc, it's a non-starter.


> "How is this different/better than taking <random web browser> and hitting "print"

If you have to repeat this process 2000 times, it becomes time consuming. It doesn't scale for a single user needing 2000 pdfs to do the process manually.


You don't know Headless Browser modes. There are a bunch of scriptable CLIs.


I do know about headless browsers. The comment above mine mentioned a manual process, no scripts or headless browsers. a combo of Curl, wkhtmltopdf(or other html to pdf) and a for loop can perform this in a bash 1-liner.


Prince is cool, I've used it 10 years ago or something. No fuss about that.

It's a bit pricey, though (at leats, pricer than "free"). So we're using WeasyPrint on more recent projects.

WeasyPrint is open source and written in Python. It's much slower than Prince, though, but this can be mitigated by caching renderings. I'm would bet that it's as standard-compliant or bug-free than Prince, but it's good enough for us.

When / if our customers ask for more speed or pixel-perfect support (with the $$$ to match), we will definitively try Prince again.


The Java class caught my eye. Is that a wrapper around a native lib or you make RPC calls to something?

HTML to PDF is something I never thought about since Firefox does it (and results usually aren’t great).


It's a wrapper around the native process just to simplify passing command-line arguments. (There is also a persistent process mode for speeding up batch processing of many small documents).

The browsers don't specialise in PDF generation, and we do :)


Whenever a language pops up on HN I excitedly look at it.

Unfortunately, the documentation, FAQ and User Guide all failed in succinctly giving me the information I need: what can it do well, what does a known snippet look like implemented in <Lang>, how does it compare to other languages, etc.

I appreciate the fact that the documentation seems extensive and well-structured, but that is only helpful to persons who already know they are going to use the language (i.e. University Students in Melbourne?).


I learned Mercury from Ralph Becket's Mercury tutorial (which is the first link under the documentation section of the site). There are code examples throughout the book that show how the language can be used.

Mercury started out as a subset of Prolog, and is still very Prolog-like. The Mercury compiler is written in Mercury, and that's how it was originally bootstrapped. So anyone that knows Prolog should feel reasonably comfortable writing code in Mercury.

One major difference is the type system, which feels more like Haskell than Prolog (where everything is an atom). Another is the way it handles predicates/functions that can generate multiple outputs - there are no cuts (!), and if a predicate can generate multiple values then it should be declared as such. These type and mode declarations allow the compiler to generate much more efficient code than a Prolog interpreter.


>> One major difference is the type system, which feels more like Haskell than Prolog (where everything is an atom).

Everything in Prolog is a "term", that can be a predicate, a constant or a variable. Constants are predicate symbols (called "functors"), numbers, or character strings of the form [a-z][A-Za-z0-9_]& (where & is the Kleene star that I don't know how to enter in HN comments), or any string enclosed in single quotes, ''. Variables are upper case letters. And predicates are atoms followed by a vector of terms in parentheses, their arguments.

There is often confusion on the matter, because all constants are considered "atomic" and people sometimes use the term "atom" to refer to all atomic constants (where the distinction is clear from the context; allegedly). However, numbers are not atoms, so the following is true:

  ?- atomic(1).
  true.
While the following, false:

  ?- atom(1).
  false.  
There is even more confusion sown by the different use of first-order logic terminology in Prolog. For example, in FOL, a "term" is a constant, a variable or a function given as an argument of a predicate, while an "atom" is a predicate symbol followed by a vector of arguments in parentheses. Perhaps the difference is partly due to the fact that it is ground atoms (i.e. without any variables) that are the most often discussed in FOL, and since constants are ground, they end up being called "atoms" in Prolog.

Then there's the fact that, in Prolog, it's impossible to distinguish between a constant and a predicate symbol or, indeed, between predicates with 0 arguments and constants. Perhaps as a result of this, Prolog accepts predicates as arguments to predicates - since it can't distinguish between 0-arity predicates and constants, it has to accept predicates as arguments, but then, it has to accept n-arity predicates as arguments. Which means that, in principle, it's a FOL language, but in practice, it is actually second-order. Maybe then the reason why predicates are known as "terms" in Prolog is because they can, actually, take the place of terms. But, I don't know for sure.

Anyway, there's a lot of terminlogical confusion around Prolog :)


> Mercury is a logic/functional programming language which combines the clarity and expressiveness of declarative programming with advanced static analysis and error detection features.

This sentence on the front page succinctly tells me exactly what to expect: the main programming paradigm (logic, functional) and its main strength (performant declarative programming). So I can imagine the language pretty well. I might not know the syntax at all, but yet I can imagine, on an AST level, how known snippets might look like. In any case showing a snippet of Hello World doesn't say much about the language itself; it at best conveys some information about syntactic choices that one gets used to very quickly.


I actually consider this statement very poor. It only appeals to programming language nerds with a wide array of experience. I see a ton of languages make this mistake, of telling me a bunch of features or properties of their language, expecting me to be interested in them for their own sake.

In order to understand this value proposition, you have to know what logic programming, functional programming, and declarative programming are and the relative strengths and weaknesses of each. Also it has a bunch of qualifiers that don't add much to the description. I know what static analysis is, but what is advanced static analysis? You also seem to have intuited that the language is performant, but that is not at all implied here.

A better statement to me would convey exactly what kind of workloads I might want to use Mercury for. As a user, I have something I want to get done, be that processing data, writing a game, or writing a network driver. I don't care about static analysis or logic programming per se. But I would if you told me it would make writing my game easier.


You probably are not the target audience then, its not that the author owes you a personal favor of any kind let alone tie everything in a bow and land it on your lap.

Plenty of people got something out of that page.


The page in general is okay. IMO they should actually lead with the second paragraph, which does mention performance, and some things you might want to do with it. They should combine that with the call out that's strangely floating off to the side that states "Mercury is a general purpose language intended to support the creation of large, reliable and efficient applications."

Here, I'll give it a shot:

"Mercury is a general purpose logic programming language that supports the development of large, reliable, efficient applications through static program analysis and a tunable execution algorithm"

From this one sentence I get the what (logic programming) why (for large reliable apps) and how (static analysis, customizable execution). Now I'm interested.


Yeah, what I was referring to when I mentioned marketing and communication design in another thread. You don't have to make false claims, you just have to shape your wording and content in order to target the right people in a more reliable way.


You can't simply judge a new language by looking at it's surface, as there are not only different languages, there are different coding styles. And then there's probably frame-works on top. So it's very unlikely that the examples will be in the style you would prefer. I think the only way to judge a language is to use it full time for at least one year, but even then you will probably just have scratched the surface. Unless you care for things that can be measured, like speed and performance. Which in case you could probably bend and twist most languages using transpilers or meta - to suit your preferred style.


> I think the only way to judge a language is to use it full time for at least one year, but even then you will probably just have scratched the surface.

In theory, that sounds nice. Have you spent a year on Rust, Go, Elm, and Crystal? If not, then what if one of them is the perfect language for that problem you're trying to solve? How can you make the right judgment call when starting a project if you haven't spent a year using each of these and more?

In reality, that's a completely absurd approach for the first-level approximation people need/want when they discover a new language... surely you realize this. People need to be able to see the big picture before they'll know whether they want to dive into the details.

There are literally thousands of programming languages. Many are created each year. How can anyone afford to spend a year, full-time, on each language to discover the truth of each language? They can't.

So I agree with dotdi:

> Unfortunately, the documentation, FAQ and User Guide all failed in succinctly giving me the information I need: what can it do well, what does a known snippet look like implemented in <Lang>, how does it compare to other languages, etc.


The programming language is not going make or break most projects. Hence the standard advice is to use a language your developers already know.

Picking an obscure language that none of your developers know well is usually not the right decision, even if the language has certain advantages over the ones you already know.


Marketing and good communication design is important though, if you want to actually reach new users. If somebody can't get the gist of what you're about from a glance, they are far less likely to invest a year into giving it a solid try.


Mercury is probably developed and maintained by a very small, even single-perrson team, at this point, so there's most likely an issue of how to best allocate resources. Perhaps the language designers just can't afford a sleek, web-based documentation system, such as other languages have.

Let's also not forget that, just because someone understands how to design and implement a really cool programming language, doesn't mean they understand how to perform "marketing and good communication". And vice-versa. These are often very different skillsets, like designing a racing car and actually racing it.

Again, it's not a given that a small team will have both those sets of skills readily at hand. Which of course, can stunt its growth, further compounding the problem.


I don't mind that it has or not a sleek documentation or just plain html. I just want one or two snippets of code in the main page.

I tried reading the docs (in the html version), and the first example is in the fourth or fifth page.


There is a tutorial in pdf format, that pretty much starts with hello world:

https://www.mercurylang.org/documentation/papers/book.pdf

  :- module hello.
  :- interface.
  :- import_module io.
  :- pred main(io::di, io::uo) is det.
  :- implementation.
  main(IOState_in, IOState_out) :-
    io.write_string("Hello, World!\n", IOState_in, IOState_out).
Is the problem that this is pdf, rather than html?


I usually try the html version first if available (and I asume that the pdf version is equal).


Yeah. One thing I don't do when looking at new languages is downloading PDF files. Actually, having documentation as PDF is a big alarm bell. I think about myself browsing PDF files if I ever end up using the language and flee in terror. Why ever invest time in formatting documentation to generate PDF?

Mercury also has HTML documentation, which is the way to go. However it's missing code samples in the home page and it's not like everybody knows about Mercury. Compare to https://www.ruby-lang.org/en/ which instead is pretty well known and still has code to show at the very beginning of the home page.


Some people prefer to print it out and read it on paper. But if you prefer to read it as a web document, why not convert the PDF to HTML !? I understand there are so many programming languages to choose from so you need to filter them out somehow, but I do not think filtering by documentation formatting is a good heuristic.


A language whose only documentation is paper or PDF (it's not the case of Mercury) is not a language that's going to thrive in this age. It's probably a waste of time to get involved with it. This is why I use documentation format as heuristic.


Additionally, ALL marketing/landing pages should back up their claims with evidence. It doesn't have to be much, but there's definitely bonus points where a short motivation is provided with links to further reading.

It doesn't have to be hard evidence exactly, but if you're claiming that something is easy, fast, "modern", what makes it so?

I concede that you can get away with it to some extent by splicing in "intended to be" in the sentence, but it still places on the visitor the burden of figuring out the "why" behind the marketing.


Oh yeah! Definitely agree with this!


I think the problem is you think everyone else know as much as you do, meanwhile the average programmer are not writing compilers and certainly don't have 30 years of field experience doing so. You imagine any serious programmer would look at your implementation and see where it's better then existing solutions, meanwhile the average programmer is blissful of not knowing the edge cases or at what scale her current tools fail. So sadly you should spend as least 50% if not more of your time at marketing and communications.


Exactly. I agree, not because of vanity, but because if a language fails to market itself well, it's probably not going to succeed in becoming adopted, and adoption breeds support in the form of open source libraries and job prospects.

Most devs don't have the time to pick up esoteric hobbyist languages because they're clever.


One can get a lot of information from examples which otherwise require a lot of literary explanations. Some examples worth more than thousand words.


> You can't simply judge a new language by looking at it's surface

I completely agree. But you also have to at least try to sell it to me. I don't have time to download the compiler, try some examples, build a little side project to find out "nope, don't like it".


> what does a known snippet look like implemented in <Lang>, how does it compare to other languages

https://rosettacode.org/wiki/Mercury


> Unfortunately, the documentation, FAQ and User Guide all failed in succinctly giving me the information I need: what can it do well, what does a known snippet look like implemented in <Lang>, how does it compare to other languages, etc.

What snippet in a purely functional programming language would be simultaneously intelligible and communicate the power of FP to someone who knew only imperative programming? I can't think of a single one that would be meaningfully representative of idiomatic FP. Making sense of FP from IP requires hard work to change your thinking on control flow and data flow.

Mercury is a constraint logic programming language. It's a fundamentally different paradigm, so you're asking for something exactly like what I described above. If you're familiar with constraint LP, then you don't need this sort of snippet, and if you're not familiar with it, I don't think any such snippet would be intelligible to you without hard work.


> What snippet in a purely functional programming language would be simultaneously intelligible and communicate the power of FP to someone who knew only imperative programming?

Propaganda about "the power of FP" was not what your parent was asking for. They were asking for code snippets. They were not asking for a program that shows off all the power of the language.

For whatever it's worth, here is Fibonacci: http://rosettacode.org/wiki/Fibonacci_sequence#Mercury and FizzBuzz: http://rosettacode.org/wiki/FizzBuzz#Mercury

> Mercury is a constraint logic programming language.

Nope. No constraints here. Also, you can mostly ignore the logic part and use it like a functional programming language.


> They were asking for code snippets. They were not asking for a program that shows off all the power of the language.

Talk about missing the main point of my comment. Code snippets that simply embed other paradigms are typically non-idiomatic or just syntactic noise if you're not familiar with the syntax. Code snippets that show off the problems for which the language is perfectly suited are unintelligible to those that don't understand the paradigm. Code snippets simply aren't all that useful if your language has a fundamentally different paradigm.

> Nope. No constraints here.

Strange because they published a paper about adding constraints years ago [1].

[1] https://www.mercurylang.org/documentation/papers/padl_solver...


> Talk about missing the main point of my comment.

I didn't miss your point. Your point was invalid. You were assuming that OP was entirely unfamiliar with functional or logic programming, and that functional or logic programming snippets would be unintelligible to them. You had no reason for these assumptions.

> Strange because they published a paper about adding constraints years ago

Ah thanks, I did not know that. The point above still stands, though: Adding an extension to what calls itself a "logic/functional" language does not make it into only a constraint logic programming language.


> You were assuming that OP was entirely unfamiliar with functional or logic programming, and that functional or logic programming snippets would be unintelligible to them. You had no reason for these assumptions.

No I didn't. I exhaustively covered all cases: "If you're familiar with constraint LP, then you don't need this sort of snippet, and if you're not familiar with it, I don't think any such snippet would be intelligible to you without hard work."

The first clause says that the high-level description as a LP language suffices if you're already familiar with such a concept and so snippets aren't of much use, and if you're not, then a snippet wouldn't help you anyway.


From the featured website: "Mercury is a logic/functional programming language". You are still going on about constraints, although they are not mentioned on the website at all. Also, before, you were going on about functional programming as if OP was not familiar with it: "What snippet in a purely functional programming language would be simultaneously intelligible and communicate the power of FP to someone who knew only imperative programming?"

Snippets would be useful for people who already know functional or logic programming. Have a nice day.


> You are still going on about constraints

Seriously? I merely quoted my original text to demonstrate a completely unrelated point, so you're the one harping on this unnecessarily.

> Also, before, you were going on about functional programming as if OP was not familiar with it: "What snippet in a purely functional programming language would be simultaneously intelligible and communicate the power of FP to someone who knew only imperative programming?"

Right, the point being made is clarified by the text I quoted. If you're familiar with it then you don't need it, and if you're not then it wouldn't help you.


I’ve written quite a bit of Mercury for fun, and I think it’s a great language. It feels more like writing in a statically-typed functional language (like OCaml) than a logic language like Prolog, despite the syntax and presence of relations. I’d love to see more people and companies adopt it; it’s a shame how important technology popularity is for most companies.


It had caught my eye but never used it. What kind of problems can I use it for?


Anything, web servers, systems programming, video games, etc. Its more of a different way of programming and thinking, using logic variables and unification to solve problems. Once you wrap your head around logic programming, its pretty easy and very powerful.

Mercury's selling poings are: - runtime performance (automatic parallelization, very efficient due to logic programming understanding and rewriting sequenced operations) - static typing (in an ml style / like OCaml) - logic programming (unification of lvars)

As a language it fills an interesting niche as logic progamming language typically aren't dyanmically typed or high performance (ie Prolog, most miniKanren implementations).

Paul Bone has some good talks on Mercury if youre interested (heres some slides from an intro talk to Mercury https://paul.bone.id.au/pub/pbone-2015-mercury.pdf)


Mercury is great at basically the same problems you would solve with Prolog, but has added purity markers that help your code not have exponential slowdowns caused by hard to discover bugs.


It's a Turing complete programming language. There are, literally, no programs you can't write in it.


I happen to co-moderate a tiny little subreddit about Mercury: https://www.reddit.com/r/mercury/ . It has a few links to blog articles with examples, slide decks, etc.

New members are more than welcome! Mercury is an interesting language, and it would be nice to bring enthusiasts a bit closer together.


> In the past when working with improper window management I have found that reaching for the rodent and lifting my eyes off my FSF emacs block cursor can trigger undesired distractions, particularly when I'm working in non-Lisp dialects (well except for mercury and Pop-11) because any idle brain wave will be spent bitching to yourself silently about the lameness of the artificial language you are forced to be thinking in presently.

- SCWM, Pot and the GPL (the Ratpoison Manifesto)


> In spite of its lack of popularity, LISP (now "Lisp" or sometimes "Arc") remains an influential language in "key algorithmic techniques such as recursion and condescension"

- A Brief, Incomplete, and Mostly Wrong History of Programming Languages


That's very funny - why don't you post it on HN?



That's very funny. Why don't you post it on HN?


I learned so much reading the papers on this website 15-20 years ago: https://www.mercurylang.org/documentation/papers.html


One interesting aspect of mercury is the number of available back-ends (grades) [1]. I'm curious if anyone has any experience using the FFI [2] for embedding mercury into a larger Java, C# or Erlang project.

[1]: https://www.mercurylang.org/about/backends.html

[2]: https://mercurylang.org/information/doc-release/mercury_ref/...


Very cool to see another active project that draws upon Prolog for inspiration.

> The benchmarks were run on a Sun SPARCserver 1000 with four 50 MHz TI SuperSPARC processors and 256 megabytes of memory running SunOS 5.3 (Solaris 2.3). Each processor is rated at 60.3 SPECint92, and has a 4-way associative 16 Kb I-cache and a 5-way associative 20 Kb D-cache, backed by 1 Mb of unified secondary cache.

What's the rationale behind such antiquated benchmarking system? Interesting.


Could it be designed to limit variance and the impact of clever hardware and its unpredictable nature? I can imagine benchmarking on a new high-end desktop machine would require a lot of work to make sure your benchmark isn't impacted because you ran it Friday at 11:44 and the cron job that runs at 11:45 messed up a few key caches, made your CPU heat up that extra 1 degree celcius causing some throttling to kick in, causing your prng to be seeded with a value that triggers a few worst-case performance scenarios etc.

There are a lot of factors that can influence a modern system and most of them seem hard to control. For a 8086 you could probably account for all these factors if you put in the hours and run it in a highly controlled environment but I doubt its even possible for a modern CPU, let alone the whole system.

Of course this isn't a problem for most benchmarks as most of them are only useful for demonstrating real world use-cases where the variance is expected and the goal is not to benchmark the performance of a single element of the system but the perceived performance you can expect in a real-world scenario.

Or its simply designed by someone who loves this kind of system and found a good excuse to put one to use.



faq in the documentation is mostly useless. but the wikipedia entry on it is quite succinct and good. but still after reading that wikipedia article and skimming through the website, i, as a typical average code monkey with a some grasp of python/js/whateva else among these lines, have no clear idea what and where mercurylang is useful for. can someone eli5-explain that to me in a few sentences?


Mercury is the love child of Haskell and Prolog: that is, a very strongly typed logic language. However, it's not quite as flexible a logic language as Prolog (owing mostly to its strong typechecking and modality system), so in practice it's closer to a Haskell with a different I/O containment mechanism (uniqueness types instead of monads) and the ability to sometimes write reversible functions if you bang your head against the modality system hard enough.

Its compiler is impressive, and is capable of acts such as compiling certain non-tail-recursive functions in a tail-recursive manner, or even transforming them into tail-recursive equivalents, given the right hints.

All this capability comes at a cost. At least as of ~4 years ago, the error messages the compiler can spit out over modality errors dwarf even those from C++ templates. And compiler bugs/unimplemented features are not unheard of.


I want to point out that Mercury is an eager language, so it's more like ML than Haskell. It does have the ability to backtrack and execute in reverse, which is kind of magical in the way people think Haskell is.

I wanted to learn it recently, but couldn't find enough example programs.


Yes, uniquenes types for IO (with proper syntactic sugar) really felt powerful, elegant and correct all at the same time.


As Mike says in a sibling comment, we use it quite heavily for implementing our HTML-to-PDF browser engine, https://www.princexml.com

It's a pretty handy general purpose language, kind of a combination of Prolog and Haskell. It's much easier to maintain a long-lived project in Mercury than one in Prolog due to the static typing, and it also generates much more efficient code. That said, it doesn't have the greatest documentation, so you might have to reach out on IRC, or the mailing list if you run into some challenges with it.


I agree with bjz_ - the documentation isn't great, and may have deterred more than a few curious individuals.

That aside, it's a pretty nifty language and I found learning it worthwhile.


The e-mail client I use (bower) is written in mercury.


Maybe a (1998) subject tag would be in order here, that's when the current web page went up. The language is much older though.

Quite influential in those times ("typed prolog" with a better compiler), but didn't gain that much attention and some mercury projects were rewritten then in other languages.


Maybe I'm just lazy, but from a quick glance, this language seems a little too wordy for my tastes... why "import_module" instead of just "import"? Or "write_string" instead of "write"? I prefer a terse programming language that uses more descriptive keywords in favor of more of them.

But I suppose that's not really the most important factor of a language and the syntax could be fun to try out.


Putting types in the keywords is sensible if you don't have multimethods/generic functions. I don't remember if Mercury has those or not.


Fairly certain I looked at this back in 2004 while I was in college.

I don’t remember too much, but my prof. thought it was cool.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: