[clean-list] New Clean Programmer

John M. Gogolin jmg@pciusa.com
Tue, 28 Jan 2003 18:33:38 -0500


Thanks Diederik,

It occurred to me about 5 minutes after I sent the question that Eq is a
class that's more restrictive than ==, isn't that the way it always
goes?  Ah well, I'm learning.

While not quite complete or following the design spec of [list] ->
[list], your example/suggestion does remind me that I should be playing
around with list comprehensions a bit more so that I get comfortable
with them.  It would make my bloody program(s) a little less of a
nightmare to read.

Regards,
John


-----Original Message-----
From: Diederik van Arkel [mailto:dvanarkel@mac.com] 
Sent: Tuesday, January 28, 2003 5:54 PM
To: John M. Gogolin
Cc: clean-list@cs.kun.nl
Subject: Re: [clean-list] New Clean Programmer


On Tuesday, January 28, 2003, at 07:24 PM, John M. Gogolin wrote:

> Hi folks,
>
> As is going to become painfully evident shortly, I'm rather new to the
> language of Clean.
>
> I've been trying to run through the exercises at the ends of the
> chapters in The Clean Book with mixed results.  The one I'm currently
> working on is the second from chapter 3, which states:
>
>     Define the function MakeFrequenceTable
>     MakeFrequenceTable [a] -> [(a, Int)] | == a
>
>     That makes a frequence table. The table consists of a list of
> tuples. Each tuple consists
>     of an element from the original list and its frequency 
> (percentage).
> E.g.
>     Frequentietabel [1,2,3,2] = [(1,25),(2,50),(3,25)]
>
> Where I run into to trouble is the "| == a" clause.  I can define the
> function as:
>
>     MakeFrequenceTable :: [a] -> [(a, Int)] | Eq a
>     MakeFrequenceTable [] = []
>     MakeFrequenceTable [x:xs] = take n (removeDup([(x, Frequence x
> [x:xs])] ++ MakeFrequenceTable (xs ++ [x])))
>         where n = length (removeDup [x:xs])
>
> with the support functions:
>
>     CountOccurences :: a [a] -> Int | == a
>     CountOccurences f [] = 0
>     CountOccurences f [x:xs]
>         | f == x = 1 + (CountOccurences f xs)
> 	           = CountOccurences f xs
>
>     Frequence :: a [a] -> Int | Eq a
>     Frequence f x = 100 * (CountOccurences f x) / length x
>
> If I try to use "| == a", however, the compiler generates the error
> "internal overloading of "removeDup" could not be solved.
>
> After digging around some, I came up with a much shorter example that
> generates the same error:
>
>     ShortenedList :: [a] -> [a] | == a
>     ShortenedList list = removeDup list
>
> How is "| == a" in conflict with "| Eq a" in these cases?  What
> fundamental piece am I not getting?  Any help here would be greatly
> appreciated.  Also, given that difference, how would one suggest 
> writing
> the MakeFrequenceTable function as per requested in the text without
> rewriting a bunch of the library code?
>
> Thanks in advance,
> John
>

Hi John,

this is a rather poor error message by the compiler. What it's trying to
tell you is that '== a' which you provide in your function type isn't
enough to satisfy 'Eq a' required by removeDup. If you insist on having
this solution and still satisfying the '== a' restriction given in the
original problem you could copy the definition of removeDup from StdList
and change the '<>' which leads to the 'Eq a' requirement into 'notEq' 
where
you define notEq a b = not (a == b), this allows you to change the class
restriction for both removeDup and MakeFrequenceTable to '== a'.

Regards,

Diederik van Arkel

P.S.

FrequenceTable l = frequencyTable (length l) l

frequencyTable n [] = []
frequencyTable n [x:xs] = [(x,length same + 1) : frequencyTable n diff]
where
	same = [e \\ e <- xs | e == x]
	diff = [e \\ e <- xs | not (e == x)]
	freq = 100 * (length same + 1) / n

(programmed in Mail, may contain errors)