Haskell refactorings
I 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)
smoothie = pour milk . runBlender . map (cut . peel)
Becomes
mkSmoothie = pour milk . runBlender . map (cut . peel)
- Extract binding
smoothie = pour milk . runBlender . map (cut . peel)
Becomes
smoothie = pour milk . runBlender . map prepareFruit
where prepareFruit = cut . peel
- Inline binding (also called Beta reduction)
smoothie = pour milk . runBlender . map prepareFruit
where prepareFruit = cut . peel
Becomes
smoothie = pour milk . runBlender . map (cut . peel)
- Eta abstraction / uncurry / make last parameter explicit
smoothie = pour milk . runBlender . map (cut . peel)
Becomes
smoothie fruits = pour milk $ runBlender $ map (cut . peel) fruits
- Eta reduction / curry / make last parameter implicit
smoothie fruits = pour milk $ runBlender $ map (cut . peel) fruits
Becomes
smoothie = pour milk . runBlender . map (cut . peel)
- Parameterizing
smoothie = pour milk . runBlender . map (cut . peel)
Becomes
smoothie liquid = pour liquid . runBlender . map (cut . peel)
Alternatively, we can keep the function as a default implementation:
smoothie = smoothieWith liquid
smoothieWith liquid = pour liquid . runBlender . map (cut . peel)
- Parameteric "polymorphization"
smoothie = pour milk . runBlender . map (cut . peel)
Becomes
smoothie mix = mix . map (cut . peel)
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.