Communication with the no-functional world.

Ana Abrão ana@ufu.br
Sat, 14 Mar 1998 19:26:49 +0000


Simon L Peyton Jones wrote:
> 
> I think this remark is absolutely true, and is true of other functional
> languages, not just Clean. 

> This is something the Haskell community has been paying quite a bit
> of attention to recently.


I am happy to see that everybody agrees on the necessity of a good
interface with the non functional world. When I wrote that stuff, I
thought that few persons would concur.

I have another wish for Clean, and I would like to know how the Haskell
community addresses it. Two or three months ago, I needed to
disassemble  Java Class files. I searched the Internet for a
disassembler. The products I got were very different from each other.
They had only one feature in common: bugs.  None was able to disassemble
my programs. A few would fail even in such staple stuff like
Animator.class.  

Since most of these disassemblers were written in C, I decided to verify
whether a program written in Clean would be more reliable. Writing the
disassembler in Clean was very easy and fun. I finished the task in 
less than one day, and I am convinced that, if my disassembler is not
bug free,  it is in much better shape than the stuff from the Internet. 
Nevertheless, whenever I make a progamming mistake, Clean compiler
feedbacks me confusing and devious error messages. For example, there is
an error in  function nHex below. Can you guess what was the message? It
was: 

"size" no instance available of type []. 

Since there is a call to "size", and the error handler was showing a
position very close to it, I was convinced that the error was there. But
no!  The error is in the expression [toHex x \\ x <- (s%(i, i+n-1))]. Of
course, I am happy that functional languages find out my mistakes at
compile  time, not at run time, as C or Java.  However, it would be much
better if  functional languages could be as good to show where the error
is, as they are good to choose when to tell me that I made a blunder.

implementation module disasm;
import StdEnv;

dis :: String -> String;
dis s
# (cafebabe, i)= head s
; (minor, i)= minorVersion s i
; (major, i)= majorVersion s i // etc.
= 
concat
  [ cafebabe
  , minor
  , major /* etc. */];

head s
| magic == ("CAFEBABE", 4) = magic
| otherwise = abort "magic number not found\n"
where {magic= nHex 4 s 0 ""};

minorVersion s i = nHex 2 s i  "\t\t;Minor version";
majorVersion s i = nHex 2 s i  "\t\t;Major version";

toHex x= ByteToHex (toInt x);

ByteToHex  x = { toHexDigit (x/16), toHexDigit (x mod 16)};

toHexDigit x
| x < 10= toChar ((toInt '0')+x)
| otherwise= toChar ((toInt 'A')+x-10);

nHex n s i c
| i > (size s - n) = abort ("Out of boundary at"+++c)
| otherwise = 
     ( comment c [toHex x \\ x <- (s%(i, i+n-1))]
     , i+n);

concat xs= foldr (+++) "" (map nuLine xs);
comment c xs= foldr (+++)  c  xs;

$ = toChar;
nuLine x = x+++{$13,$13, $10};