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