This is a bit of a long-winded introduction, feel free to skip it.
As a fledgling voice artist, I've been slowly learning the ropes of audio recording and editing. The editing facilities provided by the cheap/free wave editors that I'm aware of are, to me, cumbersome for trimming down long-form narration audio, especially for a newbie like me who makes lots of mistakes. So, I decided to try rolling my own -- something more tailor-made for voice-over in that respect.
I also thought it would be an interesting experiment to try developing it in Haskell, a language with which I've long been acquainted and have been steadily getting deeper into. GUI apps written in a purely functional language like Haskell don't seem to be all that common (though I haven't conducted an exhaustive survey or anything), and to my knowledge are still an area of active research, so I thought I'd give it a try and see what came of it.
I'm writing up my experiences developing this application here, including decision points and the thought processes behind the decisions I made, documenting the design and opening my codebase up for others to look at to hopefully give them a leg up should they decide to try pursuing something similar.
The architecture of this application was developed in an exploratory manner as I learned the different libraries I was employing, the problem domain, and a few techniques during the development, refactoring and adjusting the codebase as necessary to reflect my growing understanding of what was needed or desirable.
While the final architecture feels pretty solid to me, it's not all that flexible, so rather than prescribe it as a pattern that others should use I'm going to do a ground-up overview of the design and development process. Things are going to come across as having been more organized, coherent, and deliberate than they actually were; it's a miracle this codebase turned out to be as clean as it is.
Along the way I'm going to be drawing parallels to other technologies or design philosophies, such as web and object-oriented programming, for a few reasons:
- I assume that some people reading this will have a background without much Haskell knowledge or experience and are looking to see what's possible in a functional language, so will be better served by seeing familiar concepts
- I had been working most recently in Java before doing this application, so had an OOP frame of mind when starting out
- This application actually uses a hybrid of OOP and functional techniques: the Model-View-Presenter (MVP) pattern and Functional Reactive Programming (FRP)
That said, there's going to be plenty of Haskell-specific content -- ranging from the architecture to the boilerplate.
Even though this isn't a super-sophisticated application, it's a non-trivial one and I don't think one can get away with writing something as large as it is without using more advanced techniques/concepts, so be forewarned that we will likely be discussing or mentioning the following:
- Functional Dependencies
- Functional Reactive Programming (FRP)
- Generalized Algebraic Data Types (GADTs)
- Monad Transformers
If you're new to functional programming in general, I would recommend the following excellent resources for learning more about it:
This article was tweaked 2021-04-14 and again on 2021-06-16