uniqueness and strictness unified?

Ana Abrão ana@ufu.br
Mon, 16 Mar 1998 21:56:09 +0000


Sjaak Smetsers wrote:
> 
> Erik Zuurbier  wrote:
> >
> >Is that so? What I meant to say is that an object's TYPE can have the
> >uniqueness property, and a function cannot just have unique arguments,...etc.

Many people complain about unique types. Nevertheless, I am convinced
that the problem doesn't lie in the unique types, but in the error
reporting system. Not long ago, a certain Carlos Lopes wrote a large
music recognition program. The program needed to perform temporal
analysis (to discover the temporal position and duration of the notes)
and frequency analysis (to discover the pitch). Carlos wrote and tested
digital filters, Fast Fourier Transforms, Temporal Windows, Frequency
Shift Filters, etc, etc. All moduled worked fine, until he put
everything together. Then, Clean complained that a temporal window
needed a unique type. Since the window didn't do destructive updates, he
couldn't figure out what was going on. In fact, I went to the Canteen,
drunk some orange juice, had a long chat with friends, and came back
before he could solve the problem. He told me that, since unique types
were invented to allow destructive updates to take place, he didn't
expect them to be required on the right hand side of an arrow. I reduced
Carlo's temporal window to a one line function, so that it would fit in
a mail exchange. However, the original one was very large (about 300
lines), and was kept in a separate module. Its work was to discover the
period of a wave, by using Ferraz-Melo's algorithm.  The fact was that
the error handling system pinpointed trouble 300 hundred lines away from
the place where Carlos should insert the asterisk. Thus, I think that
Clean team should stop worrying about how to improve the unique types,
and put some work on the error reporting system.


// This is main module. File: rdWav.icl
module rdWav;
import StdEnv, fft;

// Transform a high endian 4 bytes in an integer.
Getint  xs =   sum [ x*2^y \\ x <- [toInt u\\u <-: xs] & y <-  [0, 8,
16, 32]  ];

// Number of samples per second.
NSamples xs= (Getint(xs%(40,43)))/ ((Getint (xs%(22, 23)))* (Getint
(xs%(32,33))));

// Sampling rate of a digitalized wave.
samplingRate m= toReal (Getint (m%(24, 27)));

// Read files in *.wav format.
ReadData :: {#Char} -> {#Real};
ReadData  s=  
     {scale (((toInt s.[44+2*i])+(toInt s.[45+2*i])*256))\\  i <-
[0..p2-1]}
where {
    p2= NSamples s;     
    scale  x | x > 32767 = toReal(x-65536);
   scale  x = toReal x};

stripNewLine s= s%(0, size s-2);

// Enormously simplified version of a temporal window.
// The original declaration was:
// tempWin :: {#Real} Int Int-> !{#Real};
tempWin :: {#Real} Int Int-> !*{#Real};
tempWin xs s n= { xs.[i+s]  \\ i <- [0..n-1]};

findMax :: Real  {#Real} -> Real;
findMax  sr ff= pk 0 0
where {
  power= FFT (tempWin ff 0 4096);
  pk i j | i > (size power)/2 = (toReal (j+1))*sr / 4096.0; 
  pk i j | power.[i] > power.[j] = pk (i+1) i;
  pk i j = pk (i+1) j };

Start world
  # (files, world)= openfiles world;
  (console, files)= stdio files;
  console= fwrites  "\nInputFile?" console;
  (s, console)= freadline console;
  (success, file, files) = fopen  (stripNewLine s) FReadData  files;
  (rawData, file) = freads file 200000;
  (_, files) = fclose file  files;
  world=  closefiles files world
= findMax  (samplingRate rawData)  (ReadData rawData);

//-----------------------------------
definition module fft;

Freq :: Int Int Int -> Real;

FFT ::  !*{#Real}  -> {#Real};

//------------------------------------
implementation module fft
import StdEnv

Freq :: Int Int Int -> Real;
Freq i ns nAmostras=  (toReal (i*ns))/ (toReal nAmostras);

NumberOfBitsNeeded  powerOfTwo = howMany 0
where
 howMany i
  | (powerOfTwo bitand  (1 <<  i) ) <> 0 = i
  | otherwise = howMany (i+1)

ReverseBits numBits index = reverse 0 index 0
where
 reverse i ind rev
  | i == numBits = rev
  | otherwise = reverse (i+1) (ind >> 1) ((rev << 1) bitor (ind bitand
1))

modul (re,  im)  = {sqrt(x*x+y*y)\\ x <-: re & y <-: im};

FFT ::  !*{#Real} -> {#Real}
FFT  re  = modul (Fourier (2.0*3.14159265) re (createArray (size re)
0.0))

Fourier :: !Real !{#Real} !{#Real}  -> ({#Real},{#Real})  
Fourier pi re1  im1 =   decimate 2 1 re im 
where
 sz= size re1
 nBits = NumberOfBitsNeeded sz
 sss= (map (ReverseBits nBits) [0..sz-1])
 re =  {re1.[j] \\ j <- sss}
 im =  {im1.[j] \\ j <- sss}
 decimate :: !Int !Int   !*{#Real} !*{#Real} -> ({#Real}, {#Real})
 decimate blockSize blockEnd re im 
  | blockSize <=  sz = forAllBlocks  0  re im
  | otherwise= (re, im)
 where
  delta_angle = pi / (toReal blockSize)
  sind= sin 0.5*delta_angle
  alpha= 2.0*sind*sind
  beta= sin delta_angle
  
  forAllBlocks i  re im
   | i < sz = forThisBlock i 0  1.0  0.0 re im
   | otherwise = decimate  (blockSize << 1) blockSize re im 
  where
   forThisBlock j n ar  ai re im
    |  n < blockEnd =
     let!
      k= j+blockEnd
      tr = ar*re.[k] - ai*im.[k]
                  ti = ar*im.[k] + ai*re.[k]
                  rk = re.[j] - tr
                  ik = im.[j] - ti
                  rj = re.[j] + tr;
                  ij = im.[j] + ti
                  delta_ar = alpha*ar + beta*ai
                  new_ai = ai - (alpha*ai - beta*ar)
                  new_ar = ar - delta_ar
                 in forThisBlock (j+1) (n+1) 
                     new_ar
                     new_ai 
                   {re&[k]=rk, [j]= rj} {im& [k]= ik, [j]= ij}  
    | otherwise = forAllBlocks  (i+blockSize)  re im