A few observations Re: Clean

Adrian Hey ahey@iee.org
Mon, 06 Apr 1998 16:15:59 +0100 (BST)


To the Clean Team & world at large,

For the last few weeks I've been trying out Clean on a Power Mac
and I must say that overall I'm pretty impressed. The Clean team
have obviously made a real effort to produce a package that meets
the needs of 'real world' applications programmers, rather than
simply being a research tool for academia. (It seems that you need
a Computer Science degree just to install Haskell!!)
However, without wishing to appear unduly negative, I have noted
down a few minor 'gripes' that I have and wonder what the Clean Team
(or any other Clean users) might have to say about any of these issues.

I'm afraid I must confess that I'm still a novice Clean programmer, so
perhaps I'm revealing my ignorance by griping at all.

Apologies for the length of this message, please ignore if you get
too bored.

---------------------------- Begin Gripes ----------------------------

Gripe 1 - List Expressions
--------------------------
Clean syntax for lists is a little awkward (and especially confusing
for people who regularly use several different functional languages).
e.g.
  The expression [x:xs] is a list of lists in most functional languages
  that I'm aware of.
Couldn't the ':' be made to behave more like a normal operator, rather
than being part of the punctuation of list expressions. This would make
porting programs to Clean very much simpler and less confusing.
Perhaps to retain compatibility with current Clean a pragma could be
introduced to enable this feature for those who want it.

Gripe 2 - Memory Allocation
---------------------------
When compiling a program you have to specify how much heap space and
stack space to use separately. The problem with this is how can you
really know the best values. In most cases these will depend entirely
on what data the program gets. It would help if just 1 value
(total memory to use) was supplied and the run-time system made best
possible use of this memory using stack-heap collision detection.
(Or better still, if the OS allows, the application could just grab
memory as required at run time. I suspect MacOS won't let you do this
though, since even the latest versions of this supposedly wonderful OS
don't seem to be able to sort out memory fragmentation without a
shutdown.)

Gripe 3 - Arity in Function Types
---------------------------------
The Clean system requires that the types assigned to functions aggree
with the arity of the function definition. Why? I can't think of any
reason the programmer should need to know a functions arity.
All the programmer needs to know is its type.
e.g.

// Haskell Style Ordering
:: Ordering = LT | EQ | GT;

// A utility to convert a (a b -> Ordering) to a ([a] [b] -> Ordering)
compS :: (a b -> Ordering) [a] [b] -> Ordering
compS _ []     []     = EQ
compS _ []     _      = LT
compS _ _      []     = GT
compS c [a:as] [b:bs] = case (c a b) of
                        LT -> LT
                        EQ -> compS c as bs
                        GT -> GT

// A more natural type for compS (in my humble opinion) might be:
compS :: (a b -> Ordering) -> ([a] [b] -> Ordering)

// but to use this you must re-write compS thus..
compS c = comp
   where comp []     []     = EQ
         comp []     _      = LT
         comp _      []     = GT
         comp [a:as] [b:bs] = case (c a b) of
                              LT -> LT
                              EQ -> comp as bs
                              GT -> GT

Not only is this second definition of compS unnecessarily complex but
it may also be slightly slower (I'm afraid I don't know enough about
the Clean implementation to be sure of that fact, so I apologise if
I'm wrong!)

I appreciate that at the machine level implementation it is necessary to
know how many arguments a 'graph-rewriting' routine actually requires,
but surely this information could be generated automatically by the
compiler and hidden away somewhere in the Clean System Files.

This may seem a minor point, but it causes me real grief when I use
synonyms for function types (as I often do). It would appear that
whoever wrote the parser combinators detailed in chapter II.5 of the
'Functional Programming in Clean' book had the same problem.

Gripe 4 - Module System
-----------------------
I like the Clean style of Module interfaces (.dcl files) a lot.
Its definitely preferable to the 'bag of names' approach used in Haskell,
but do the interfaces really have to be in separate files. Having to
maintain two files per module isn't too bad in GUI environment, but I
guess most users would prefer to just work with one file or window per
module. One of the main headaches with C is having to maintain all
those wretched header files, now Clean requires us to do the same.
Instead, couldn't each module have separate 'public' and 'private'
sections in one file.
(This isn't such a trivial point, many commercial companies operate a
QA system that requires a whole load of paper work to be raised every
time a source file changes. If both the .icl and .dcl files need
changing then twice as much paper work needs to be raised.)

Gripe 5 - No 'Ordering' primitives
----------------------------------
Clean provides the usual set relational operators, but doesn't have the
equivalent of Haskell's Ordering comparison function for 'built in'
types (which is very useful I think).
If you want it you can define it thus..

// Function to compare two Ord's
cmpOrd :: a a -> Ordering | Ord a
cmpOrd x y | x<y = LT
           | x>y = GT
                 = EQ

but this may require two invocations of relational operators
(1.5 on average I suppose), which may slow things down a little.

Gripe 6 - Documentation
-----------------------
I have noticed that the currently appears to be very little
supporting documentation for new language features and libraries.
I know generating documents is awfully time consuming (I spend far more
time doing this than actually writing software), but if you want Clean
to be accepted for use in commercial environments high quality user
documentation is essential.

Gripe 7 - No Acorn RiscOS port
------------------------------
Sorry, but I'm an Acorn fan. I know there's not many Acorn users in
the world, but those that there are tend to be fairly computer literate
(thats why they're Acorn users). I'm sure many of them would be happy
to give Clean a try if it was available to them.

----------------------------- End Gripes -----------------------------
But I'm not finished yet...
I have couple suggestions for future Clean releases:

1/ It would be really useful if the Clean IDE provided help with
   'configuration control' for maintainance of large projects.
   e.g. keep certain base line releases un-corrupted
        provide a tool for keeping track of change records.
   (This sort of thing is more or less mandated by QA these days).

2/ Provide a means for automatic generation of simple test harnesses
   for individual modules. Perhaps by allowing the insertion of test
   'assertions' which are simply boolean expressions which must
   evalute to True. It would be fairly simple to convert the list
   of assertions into a simple program which evaluates each expression
   and reports any which turn out False. You could even get the IDE
   to run the test harness each time a module is compiled.
   (Again, this sort of thing is more or less mandated by QA these days
    and doing it manually is a real chore).
   P.S. I know Functional Programmers would prefer to 'prove' software
   is ok using predicate calculus and structural induction or some such
   thing, but I'm talking about the real world here :-)

Regards
--
Adrian Hey