I am writing a program with several functions that take the same arguments. Here is a somewhat contrived example for simplicity:
buildPhotoFileName time word stamp = show word ++ "-" ++ show time ++ show stamp
buildAudioFileName time word = show word ++ "-" ++ show time ++ ".mp3"
buildDirectoryName time word = show word ++ "_" ++ show time
Say I am looping over a resource from IO to get the time
and word
parameters at runtime. In this loop, I need to join the results of the above functions for further processing so I do this:
let photo = buildPhotoFileName time word stamp
audio = buildAudioFileName time word
dir = buildDirectoryName time word
in ....
This seems like a violation of "Don't Repeat Yourself" principle. If down the road I find I would like to change word
to a function taking word
, I might make a new binding at the beginning of let
expression like so:
let wrd = processWord word
photo = buildPhotoFileName time wrd stamp
audio = buildAudioFileName time wrd
dir = buildDirectoryName time wrd
in ....
and would have to change each time I wrote word
to wrd
, leading to bugs if I remember to change some function calls, but not the others.
In OOP, I would solve this by putting the above functions in a class whose constructor would take time
and word
as arguments. The instantiated object would essentially be the three functions curried to time
and word
. If I wanted to then make sure that the functions receive processWord word
instead of word
as an "argument", I could call processWord
in the constructor.
What is a better way to do this that would be more suited to Functional Programming and Haskell?