Recently I’ve been working on a toy project which involves being able to both read in and write to a .wav sound file. Fortunately, I had previously written this functionality in C for a school project. I had heard of Haskell’s function interface before, and figured this would be a good opportunity to learn it.

What I found was a language feature which is at one time quite easy to use, while at the same time difficult to find out how to use. The specifics of how a .wav file works shouldn’t be important to understanding this article.

To give the setup, I have this functionality written in C, split across wave.h which defines the struct and wave_lib.c which contains the code for reading and writing a file:

//wave.h

typedef struct {

uint32_t sampleRate; // samples per second

uint32_t dataSize; // number of bytes of data

uint16_t numChannels; // number of channels per sample

uint16_t bytesPerChannel; // how many bytes each channel gets

char *data;

} WAVE; //wave_lib.c

WAVE *readWave(char *fileName);

void writeWave(char *fileName, WAVE *w);

And my goal is to use this end up with this functionality in Haskell:

data Wave = Wave

{ sampleRate :: Int

, dataSize :: Int

, numChannels :: Int

, bytesPerChannel :: Int

, waveData :: [Char]

} readWave :: String -> IO Wave

writeWave :: String -> Wave -> IO ()

If you have experience with the foreign function interface, you may be wincing at the types used above- we’ll address that soon enough.