Discussions related to Visual Prolog
pauljouet
Posts: 4
Joined: 2 May 2021 8:06

Predicate declaration for using recursion on lists of objects with custom type

Unread post by pauljouet »

Hello,

I am beginning with Visual Prolog and encountering an issue with a predicate declaration. My predicate should be used in order to extract string values within custom objects 'inw', which are contained in a list of lists of lists, but I also want to keep the lists of lists structure. I tested this predicate using SWI Prolog :

Code: Select all

inw_str([],[]):-         !. inw_str([H|T], Words):-         H=inw(Word,_,_),  % Word is the relevant string value that I want to keep         inw_str(T,Acc),         Words= [Word|Acc]. inw_str([H1|T1], [H2|T2]):-         inw_str(T1,T2),         inw_str(H1,H2).
Used like this:

Code: Select all

?- inw_str([[[inw(bonjour, b,c), inw(le,d,e), inw(monde,f,g)],[inw(salut, h,i),inw(ca, d,d), inw(va,v,v)],[inw(test,c,c)]],[[inw(bonjour, b,c), inw(le,d,e), inw(monde,f,g)],[inw(salut, h,i),inw(ca, d,d), inw(va,v,v)],[inw(test,c,c)]]], Res). Res = [[[bonjour, le, monde], [salut, ca, va], [test]], [[bonjour, le, monde], [salut, ca, va], [test]]] ; false.
There it works as intended, however in Visual Prolog, the issue is that I cannot declare the input to be either inw* or inw*** or just inw, I always get an error looking like :

error c504 : The expression has type 'database::inw', which is incompatible with the type 'database::inw*'
(with inw* as declared input type)

or

error c504 : The expression has type 'A', which is incompatible with the type 'database::inw'
(when I use A* as input type)

This is likely due to the third clause, where I use H1 as input (and it is not legal to Vprolog). I tried creating a custom domain but I am still not comfortable with that and it did not work.

(error c504 : The expression has type 'A$*', which is incompatible with the type 'database::inw_cpnd')

Is there any simple way to solve this problem ? Should I quit using this kind of recursion ? Is there a correct way to declare the domain that I should use ?

Thanks,
Paul
Harrison Pratt
VIP Member
Posts: 353
Joined: 5 Nov 2000 0:01

Re: Predicate declaration for using recursion on lists of objects with custom type

Unread post by Harrison Pratt »

Look at your 3rd clause. H2 must be a string in the clause head, but in the last line it is a string_list. You need to create the output list you tried to represent as [H2|T2] within the clause.

Code: Select all

inw_str([H1|T1], [H2|T2]):-         inw_str(T1,T2),         inw_str(H1,H2).
User avatar
Thomas Linder Puls
VIP Member
Posts: 1253
Joined: 28 Feb 2000 0:01

Re: Predicate declaration for using recursion on lists of objects with custom type

Unread post by Thomas Linder Puls »

In ISO-Prolog there are no types, and some ISO-prolog terms are not typeable in Visual Prolog and will subsequently not be valid, and hence not exist.

Let us first consider your test data, it contains sub-terms like this:

Code: Select all

bonjour
In ISO-Prolog such terms just exists and you have have whatever name/string you like. In Visual Prolog you will have to decide whether 'bonjour' is one of the values a fixed predefined/enumerated set of values. If it is then you can define the domain like this:

Code: Select all

domains     word =         bonjour;         le;         monde;         salut:         ca;         va;         test.
Such a domain will defines the exact set of values that can be used.

My guess is that such enumeration types is not what you have in mind here, and in that case you will have to use strings instead in Visual Prolog:

Code: Select all

inw("bonjour", "b", "c")
In your test data all the inw-terms have that form inw(<string>, <string>, <string>), and that would correspond to a domain like this:

Code: Select all

domains    inw = inw(string Word, string X, string Y).
OK, that was the "simple" difference between ISO and Visual Prologs terms.

The more difficult one is that in ISO-Prolog any term is allowed anywhere, so you can call a predicate with an inw-term or a list of something, or a string or a number or whatever you like. And you can also write clauses to take care of any of these cases.

But in Visual Prolog a term/type is either an inw-term/inw-type or a list term/list type. You cannot mix inw-terms and list terms like that.

Your test data is valid in Visual Prolog, but it has type inv*** (list-of list-of list-of inw):

Code: Select all

constants     test : inw*** =         [             [                 [inw("bonjour", "b", "c"), inw("le", "d", "e"), inw("monde", "f", "g")],                 [inw("salut", "h", "i"), inw("ca", "d", "d"), inw("va", "v", "v")],                 [inw("test", "c", "c")]             ],             [                 [inw("bonjour", "b", "c"), inw("le", "d", "e"), inw("monde", "f", "g")],                 [inw("salut", "h", "i"), inw("ca", "d", "d"), inw("va", "v", "v")],                 [inw("test", "c", "c")]             ]         ].
But this term (which is valid in ISO-Prolog) does not exist in Visual Prolog:

Code: Select all

constants     illegal : ??? =         [             [                 [inw("bonjour", "b", "c"), inw("le", "d", "e"), inw("monde", "f", "g")],                 [inw("salut", "h", "i"), inw("ca", "d", "d"), inw("va", "v", "v")],                 [inw("test", "c", "c")]             ],             [inw("bonjour", "b", "c"), inw("le", "d", "e"), inw("monde", "f", "g")],             [inw("salut", "h", "i"), inw("ca", "d", "d"), inw("va", "v", "v")],             [inw("test", "c", "c")]         ].
Some parts have three levels of list but other parts are only two levels and that not legal in Visual Prolog all elements in a list must have same type (and different levels of list makes different type).

Your clauses deals with (assumes) an arbitrary level of lists, and that is where problem with giving the clauses a type comes from.

I am not really sure whether you want arbuitraty levels of lists of if you actually have a more "rigid" list struct in mind like in these domains:

Code: Select all

domains     chapter = paragrap*.     paragraph = sentence*.     sentence = inw*.     inw= inw(string Word, string X, string Y).
But assuming that you want arbitrary levels of lists in a proper solution to your entire problem could be like this:

Code: Select all

implement main   domains     inw = inw(string A, string B, string C).   domains     nestList{Type} =         one(Type);         list(nestList{Type}* List).   constants     test : nestList{inw} =         list(             [                 list(                     [                         list([one(inw("bonjour", "b", "c")), one(inw("le", "d", "e")), one(inw("monde", "f", "g"))]),                         list([one(inw("salut", "h", "i")), one(inw("ca", "d", "d")), one(inw("va", "v", "v"))]),                         list([one(inw("test", "c", "c"))])                     ]),                 list(                     [                         list([one(inw("bonjour", "b", "c")), one(inw("le", "d", "e")), one(inw("monde", "f", "g"))]),                         list([one(inw("salut", "h", "i")), one(inw("ca", "d", "d")), one(inw("va", "v", "v"))]),                         list([one(inw("test", "c", "c"))])                     ])             ]).   class predicates     getInwWords : (nestList{inw} Inw) -> nestList{string} WordList. clauses     getInwWords(one(inw(Word, _, _))) = one(Word).     getInwWords(list(List)) = list(getInwWords_list(List)).   class predicates     getInwWords_list : (nestList{inw}* InwList) -> nestList{string}* WordList. clauses     getInwWords_list([]) = [].     getInwWords_list([H | T]) = [getInwWords(H) | getInwWords_list(T)].   clauses     run() :-         Words = getInwWords(test),         stdio::writef("Words = %\n", Words).   end implement main   goal     console::runUtf8(main::run).
The way I have dealth with arbitraty list level is to have a functor domain (nestList) which is:
  • either one element or
  • a list of a such nestList "things"
I have made the domain polymorphic (parameterized over the Type of the elements), that way it can be used both for the:
  • nestList{inw} the input of the predicate and
  • nestList{string} the output of the predicate
I have also split the predicate in two and turned it into a function (which has no pendant in ISO-Prolog).

This is probably a big mouthful so don't hesitate to ask more.
Regards Thomas Linder Puls
PDC
pauljouet
Posts: 4
Joined: 2 May 2021 8:06

Re: Predicate declaration for using recursion on lists of objects with custom type

Unread post by pauljouet »

Thank you very much for your reply, you well pointed out my problem. In fact, my structure is quite rigid, so I do not necessarily need to deal with arbitrary levels of nesting. Nevertheless, I was really interested in knowing how it would have to be handled. Your solution unfortunately requires me to change the form of my input data, so the simplest for me will probably be to deal with each level of nesting separately.

I will take a closer look at the code you shared, and reply to the same topic if I have any further questions.

Thanks again,
Paul
Post Reply