[mercury-users] more Mercury homework: "Mercuryfy" some simple Prolog

Paul Bone pbone at csse.unimelb.edu.au
Fri Sep 24 09:45:04 AEST 2010


On Thu, Sep 23, 2010 at 04:30:15PM +0200, Jean-Marc Vanel wrote:
> Hi
> 
> I'm in the middle of translating into Mercury some simple Prolog from the
> book "the Art Of Prolog" , namely Program 2.1:  Defining family
> relationships :
> 
>         uncle(Uncle,Person) :-
>                 brother(Uncle,Parent), parent(Parent,Person).
> 
> And, again, I do not find much help in the documentation.
> 
> First , I put this is interface :
> :- type person.
> 
> But, then, what to put in the implementation, which would the equivalent of
> an empty class in Java ?

You don't want to think in a 'Java way' when writing Mercury.  OO languages
have classes so that methods can be defined on objects of those classes, It
doesn't look like you need that, but you may want to read about Mercury's
typeclasses to see how to do that when you do need to.  (A Mercury typeclass is
like a Java interface, it has no concrete data or methods).

You want to decide what a data you need to identify a person within your
program.

It might be simple enough that person is only a first name or nick name

    :- type person == string.

or

    :- type person
        --->    person(
                    first_name          :: string
                ).

But in some applications they may need a last name and an address.

    :- type person
        --->    person(
                    first_name          :: string,
                    last_name           :: string,
                    address             :: address % Define address separately.
                ).

Some people might not have a last name though, like Cher, or the artist formally
known as Price and once again called Prince )O think he changed his name back
to "Prince").

    :- type person
        --->    normal_person(
                    first_name          :: string,
                    last_name           :: string,
                    address             :: address % Define address separately.
                )
        ;       crazy_person(
                    % This could also be an innocent child with crazy parent(s).
                    crazy_name          :: string
                ).

This data type is a discriminated union, it can represent either a normal
person, or a crazy person, but not both at the same time.  Normal people are
guaranteed to have a first and last name, and an address.

As for design, start with something simple and extend it if you need too.  You
probably don't need to represent crazy people or use typeclasses in this
example.

> A 2nd problem is with pure database predicates (primitives), like brother. I
> put this :
> :- pred brother( person, person) is multi .
> :- mode brother( in, out ) is multi .
> :- mode brother( out, in ) is multi .
> 
> But the compiler is not happy :
> Error: no clauses for predicate `brother'/2.
> 

Just write clauses,

brother("Paul", "James").
brother("James", "Paul").
brother("Keith", "Robert").
brother("Robert", "Keith").

Make sure you define now a girl who has a brother is defined, which is
different to a boy who has a sister.  One of the below two clauses is an error
because Sarah is not Matt's brother.  But which one?

brother("Matt", "Sarah").
brother("Sarah", "Matt").

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/users/attachments/20100924/851a40ad/attachment.sig>


More information about the users mailing list