After more experimentation, I have found the problem only occurs when the auxiliary function is declared in a “where” clauses, as was done in all of my attempts.  If I move all definitions to the file scope, the programs work as I expect.  The attached program demonstrates this.

 

Is this behavior expected?  My understanding is that the only difference between the two declaration types is name visibility.  Am I wrong?

 

Perhaps this issue is related to the use of default rules?  I didn’t see any mention, e.g., here, that they must be defined at file scope, but maybe that is necessary?

 

-Andy

 

From: Andy Jost
Sent: Saturday, July 3, 2021 3:44 PM
To: 'curry@lists.RWTH-Aachen.DE' <curry@lists.RWTH-Aachen.DE>
Subject: Recursion in Set Functions

 

Hi,

 

I have run into an unexpected (to me) behavior when using set functions.  I want to write a function that calculates a “penalty” that equals the number of times any character repeats three times in a string.  For example, “aaaa” has penalty two, while “aabaa” has penalty zero.

 

I thought it might be fun to use a functional pattern, so I wrote the following:

 

penalty1 (b++[x,x,x]++e) = 1 + penalty1 (b++[x,x]++e)

penalty1'default _ = 0

 

Although this works, it scales as the factorial of the longest substring of repeated characters.

 

I thought I could improve it by introducing a set function and then using selectValue to cut down the search space.  My idea was to recursively remove one character from an arbitrary triple, repeating until there are no more triples and counting the iterations.  Rather than choosing every way to remove a character, I just want to choose one of them.

 

I tried coding this several ways (below), but each time the result is “no value found.”  I am using PAKCS 3.3.0.

 

Is this the expected behavior?  Does it suggest a problem with the implementation of set functions or with my understanding of them?  Can anyone point towards a solution using functional patterns?  Other methods -- e.g., a pure-Haskell solution -- are trivial, so there’s no need to point them out.

 

Thanks,

-Andy

 

 

penalty2 pw = selectValue $ (set1 aux) pw

    where

        aux (b++[x,x,x]++e) = 1 + penalty2 (b++[x,x]++e)

        aux'default _ = 0

 

penalty3 pw = selectValue $ (set1 aux) pw

    where

        aux (b++[x,x,x]++e) = 1 + aux (b++[x,x]++e)

        aux'default _ = 0

 

penalty4 pw = let pw' = next pw in if pw' == [] then 0 else 1 + penalty4 pw'

    where

        next pw' = selectValue $ (set1 aux) pw'

        aux (b++[x,x,x]++e) = b++[x,x]++e

        aux'default _ = []