[m-users.] Functions vs Predicates?
jfischer at opturion.com
Thu Oct 29 13:49:53 AEDT 2020
On Wed, 28 Oct 2020, Qqwy/Wiebe-Marten wrote:
> I am a programmer with quite a bit of background in Haskell and
> Elixir/Erlang (as well as some other languages) and some beginner
> experience in Prolog.
> As I like statically-typed languages very much, I was excited to
> discover Mercury and have now read through the various beginner
> tutorials and a big part of the users guide and language reference.
> There is one thing that is puzzling me, however: Mercury has both
> `pred`icates and `func`tions.
> At first I thought that `func`s were "syntactic sugar" around a
> predicate which always flows in a single direction
> (which therefore would need less manual type annotations as the compiler
> does not need to infer as much).
That's correct, functions are mostly syntatic sugar. They have a few
extra things associated with them such as the default function modes.
As syntatic sugar, they have the property of composing more nicely than
predicates (e.g. in arithmetic expressions), that's one of the principle
reasons for using them.
> However, later on I read that `func`s can also be used backward.
> This puzzles me, because now I am confused as to when I should use a
> `pred` and when a `func` in my own code.
> What confuses me further is that there are e.g. functions like
> `univ_to_term` and `term_to_univ`
> which seem like perfect candidates to have been written as a single
> reversible `term_univ(Term, Univ)` predicate instead.
The function term_to_univ does not exist. In general those two
opertions are not invertible, the context associated with the term
may not be preserved.
That said: I would argue that it is easiser to comprehend the intent
of code using the former two names and that such code is unlikely to
be usefully reversible anyway.
Aside: I find that most introductory logic programming / Prolog texts tend
to overrate the importance of being able to make operations reversible;
it's a cute trick but of very limited utility in non-trivial programs.
> When is it more idiomatic to use a function, and when to use a predicate?
The language definition is mostly agnostic on that point; to some extent
it tries to encourage you to treat function as functions (e.g. through the
existence of the existence of the default function modes etc).
In the Mercury implementation itself, the usage we typically follow is:
* Deterministic operations with a single output are functions.
* Operations that can fail are predicates.
* Operations with multiple outputs are predicates (not functions that
return tuples as in, for example, Haskell).
More information about the users