Haskell refactorings
Gautier DI FOLCO February 11, 2024 [Software engineering] #software engineering #design #haskellI was looking through Martin Fowler's refactorings list which is heavily OOP/Imperative-oriented.
There are currently 66 refactorings:
- 27 are focused on local rearrangement (locally move piece of code, renaming)
- 4 are focused on pure encapsulation
- 35 are focused on responsibilities distribution amongst OOP concepts
Note: responsibilities distribution is often involving encapsulation, but I have done my best to make a distinction between refactorings which are more agnostic and those working through OOP concepts.
If I try to summarize which refactorings I use, there are far less.
- Rename (also called Alpha conversion)
= pour milk . runBlender . map (cut . peel)
smoothie
Becomes
= pour milk . runBlender . map (cut . peel)
mkSmoothie
- Extract binding
= pour milk . runBlender . map (cut . peel)
smoothie
Becomes
= pour milk . runBlender . map prepareFruit
where prepareFruit = cut . peel
smoothie
- Inline binding (also called Beta reduction)
= pour milk . runBlender . map prepareFruit
where prepareFruit = cut . peel
smoothie
Becomes
= pour milk . runBlender . map (cut . peel)
smoothie
- Eta abstraction / uncurry / make last parameter explicit
= pour milk . runBlender . map (cut . peel)
smoothie
Becomes
= pour milk $ runBlender $ map (cut . peel) fruits
smoothie fruits
- Eta reduction / curry / make last parameter implicit
= pour milk $ runBlender $ map (cut . peel) fruits
smoothie fruits
Becomes
= pour milk . runBlender . map (cut . peel)
smoothie
- Parameterizing
= pour milk . runBlender . map (cut . peel)
smoothie
Becomes
= pour liquid . runBlender . map (cut . peel)
smoothie liquid
Alternatively, we can keep the function as a default implementation:
= smoothieWith liquid
smoothieWith liquid = pour liquid . runBlender . map (cut . peel)
smoothie
- Parameteric "polymorphization"
= pour milk . runBlender . map (cut . peel)
smoothie
Becomes
= mix . map (cut . peel)
smoothie mix
That roughly 7 refactorings for local rearrangements, and these are probably 90%-95% of the refactorings I use daily (and I use them a lot).
Sure, there are few others at type-level but despite that, there are far less than in the OOP ecosystem.
Which does not seem intuitive to me as Haskell (at least GHC's version) is a quite large programming language compared to other OOP programming languages. I guess FP simpler core plays a role in that.