Functional Refactoring and "You Can't Get There From Here" 74
I’ve been working in Haskell recently, and I find myself doing much less refactoring. In fact, I rewrite more than I refactor.
I’m not talking about massive refactoring, but rather the sort of micro-refactoring that I do to move from one algorithm to another. If you are working in an imperative language, you can often make micro waypoints – little testable steps along the way as you change your code from one shape to another. You can add a variable, confident that behavior won’t change because you haven’t used it yet, and you can move one statement down below another, changing the order of a calculation if (again) you are confident that the overall computation is order in variant. As I TDD my code, I do those sorts of things. I often refactor by introducing a parallel computation in the same method as the old one, and if the test passes, I knock out the old way of doing things and leave the shiny new one.
In Haskell, however, I don’t do that, and it reduces the amount of time that I spend refactoring. Yes, I rename variables, add parameters, and introduce where-clauses, etc. But, refactoring in Haskell seems different, and I think I know why now. There are two reasons and they sort of intermingle.
Imperative programs are built of little state changing variables, and one of the effects is that you can have lots of little bits changing independently. It’s rather easy to add mutating state variables and have “several calculations in the air” in a method while you are along the way toward reducing it to one. In functional programming, however, you use bigger pieces. Instead of looping, you use map or fold – you end up with terse code which packs a lot of punch.
Here’s a function which determines a position within a document from a column/row coordinate (affectionately named x and y here):
absPosition :: Buffer -> Int
absPosition (Buffer (x, y) contents) = x + lenPreviousLines contents
where lenPreviousLines = foldr ((+).length) 0 . take y . terminatedLines
The thing to get from this example if you don’t read Haskell is that it is fully compositional. Each of the dots in the definition of lenPreviousLines is a composition operation. We apply the terminatedLines function to a string, and take its output and pass it to the function ‘take y’, then we pass its output to ‘foldr ((+).length) 0’. The net effect (take my word for it) is that we end up with the sum of the lengths of a set of text lines.
That small piece of code performs a rather large chunk of work. It takes a string, splits it into lines, appends a newline to each line, takes y of the lines and then sums the count of their characters. But, to me, that’s not the interesting part. The interesting part is that it is tight. There is no space for a parallel computation, no place where you can perform some computation off to the side and progressively move toward a different algorithm. If you want to change the algorithm you essentially rewrite it – you replace some chunk of that code with another chunk of code.
One of the beautiful things about pure functional programming is that it eliminates side effects. That, by itself, might not impress you, but the thing that it enables is very powerful, when you remove side effects you lose all barriers to composability. It’s easy to make little tinker-toy-like parts which you piece together to do your work, and, in fact, that’s exactly what has happened in Haskell. Most of the time, you can find a little function which will do what you want. You don’t often have to drop down into primitive list operations or recursion. Instead, you have this substrate of little composable bits. We don’t have anything like that in traditional languages. We drop down to loops, assignment and mutable variables all the time.
The end result, I think, is that a lot of refactoring in Haskell is more like rewriting, or (to be precise) it is more like the ‘Substitute Algorithm’ refactoring in Martin Fowler’s Refactoring book. In pure code, there isn’t any extra bandwidth for building up parallel computations. The pieces are bigger, so many refactorings are more like leaps than micro-adjustments toward a goal.
Is this good or bad? I don’t know. I think it is just different. Personally, I’m happy to have higher level pieces, although, I have to admit, I sometimes miss the fluidity of work with more granular primitives. It’s a place you can always drop down to and build back up from. In Haskell, at the micro-level, you have to fix your sights on a new target and rebuild.
Refactoring in functional programming languages is different, I agree. However, it is possible to do it smoothly, rather than rewriting in big chunks. Paul Hudak has some awesome examples of smooth manipulations in his book “Haskell School of Expression”.
Don’t throw up your hands and say “it’s different”. Yes, it’s different, but that move is always available – it’s too easy.
Two of the primary moves in functional refactoring are expansion “replace a function with its (anonymous) definition”, and contraction “replace an (anonymous) function with a call to an existing procedure”. Elegant chains often look like “expand-expand-expand-contract-contract-contract”.
Johnicholas: Yes, I do that. The bit which I don’t do is build up a parallel computation in place, and use it to replace what was there. It also seems that when I add new functionality, I have to replace what I have for the next case rather than perform a minor refactoring. It’s manageable, but a bit different.
BTW, I like Hudak’s book quite a bit. I was my first Haskell book.
Can you talk a bit more about TDD in Haskell? I was having good luck on the bottom ‘layer’ of what I was working on, but trying to test-drive higher stuff (that composed those others) was quite hard for me – had to do a lot of setup. Maybe I am just going about things wrong – I still don’t have a good idea how to structure Haskell programs overall.
I think type-classes are underused in idiomatic Haskell. Working with those gives you both the ability to test with mocks, and often the ability to refactor. Particularly, classical FP tends to need a million little changes when you change the data definition, but accessing data through type-classes gives you protection.
I know you’re learning but a couple of statements are completely out of whack.
“Imperative programs are built of little state changing variables, and one of the effects is that you can have lots of little bits changing independently.”
Actually, imperative programs, by their very definition, have little bits that are not little bits after all, since they are not independent. This is the essence of the whole problem of imperative programming.
“when you remove side effects you lose all barriers to composability.”
No, quite the opposite, when you remove side-effects, you break down barriers to composability.
I think you’re one step before realising that “refactoring” is a bunk concept that (poorly) works around bad programming practices.
When you want to “change the behaviour” of that pure function, why the aversion to writing a new function? Why does the original one need to be “refactored”? The answer runs deep, so spare some time for yourself.
@Julian There is an enlightening example of this in RWH that demonstrates use of type-classes in a testing context for monadic code (but could be any typeclass of course). Nice thing about it is that it is deeply related to something that has become prominent in OO testing: test and mock to interfaces you own, thus creates your own abstraction that wrap standard or low-level interfaces.
But you may know it already :-)
@michael did you try to install/use HaRe ? it seems a little bit dormant (or so was it last time I checked…) but promised to offer some useful tools for doing simple refactorings. The ones I am missing most is the ability to rename and ‘extract function’.
““when you remove side effects you lose all barriers to composability.”
No, quite the opposite, when you remove side-effects, you break down barriers to composability.”
I think you don’t read so good. And you’re mean.
@Carl:
That’s Tony Morris for you. Do like we all do on the various FP mailing-lists: read his messages just to discover what other twisted wording he’ll come up with to make fun of the person he responds to but ignore the content of his messages, which is often wrong anyway (this one is no exception).
I think Tony Morris is saying something interesting: if you just write a second function then you have two parallel paths (the new one and the old one) which are much easier to test against each other than if you had two (heap-changing) algorithms in a single method. You could, for example, auto-generate test data and throw it at both versions pretty easily. When there are discrepancies you can look to see whether the new one or the old one handled it better.
Concerning both refactoring and rewriting a function, we Haskellers also rely a lot on the type checker to keep us on the right path. Of course, strong type checking cannot replace a rigorous testing discipline, but it makes you more confident to take bigger steps.
Oops .. for entering my email instead of the name.
You can always introduce a let and name those intermediate results, and then there’s plenty of room for parallel versions, if you really want to change things incrementally.
Not sure I’m adding much here, but when I was working with CAL (http://openquark.org/ – a Haskell-like language which compiles to Java bytecode) I found the same.
I’d solve the problem one way, learning much about it, then almost completely rewrite it. I guess this is much more akin to prototyping than refactoring, which isn’t itself a bad thing IMHO. Wasn’t it Brooks that said: “Plan to throw one away; you will anyway”?
I like to work in Lisp (functional programming) when ever I can. I originally learned it the 70s before we bothered with things like TDD. But I do things differently now. What I have learned to do now is create a stack of failing unit tests.
You drive your code from the top level by adding a test that fails. You go to fix your code and notice you need a new function. You stop and create another unit test for that function. Now as you create that function you notice you need yet another function. So you create a failing unit test for that.
Now you have 3 failing unit tests in a stack. When I get the current unit test done I will push another on the stack until my function is done, then pop the stack. Now I have the function I need to get the next test running. I can now test my function into existence and pop the stack again. I use the function I just created to get the last unit test running.
So, now to refactor. I decide to change some function by calling some new function, so I write unit tests to test that new function into existence then continue my refactoring. If I find a function not being used I delete it and all of its tests.
“If you want to change the algorithm you essentially rewrite it – you replace some chunk of that code with another chunk of code.”—that’s pretty much how I’d describe the activity of refactoring; you seem to be taking a more limited definition than I would use.
Using let or where bindings to pull out pieces of a computation and experiment with alternatives is very good advice. But also, I find myself coding large complex actions on lists on the first pass as big recursive loops, then pulling out bits of common structure into smaller pieces. I suppose the difference is that you can always step back and look at the whole chain of computations, so refactoring will tend to involve altering where/how the chain is broken up to make things more logical. Eliminating superfluous points and soforth as well.
foldr ((+).length) 0 . take y . terminatedLines for example could become (sum . map length . take y . terminatedLines)—moving from explicit folds up to more restricted combinators is an abstraction win i think, though your milage my vary.
At which point I’d probably decide the where clause was superfluous and inline it back into the function yielding: x + (sum . map length . take y . terminatedLines $ contents). I’d then turn the plus into a section, getting: (x+) . sum . map length . take y . terminatedLines $ contents.
At this point I’d see that adding x when I’m already summing is sort of silly, and maybe rewrite it as such: sum . (x:) . map length . take y . terminatedLines $ contents.
This now expresses that the sum is of the length of y terminated lines, along with the x position.
Your taste and mileage may vary of course.
sterl: Thanks for your suggestions. I incorporated them and added some musings here: http://blog.objectmentor.com/articles/2009/08/11/naming-and-body-language-in-functional-code
cheap VPS
Hermes belt, Hermes belts, Hermes Mens belts, Hermes belts for men.
To get the beachy, wavy look it helps if your hair has some natural wave to it and this look works on hair of almost any length, even chin-length hair or a bit shorter.
gucci wallet, gucci wallets, mens gucci wallet, women gucci wallet.
To get the beachy, wavy look it helps if your hair has some natural wave to it and this look works on hair of almost any length, even chin-length hair or a bit shorter.
louis vuitton wallet, louis vuitton wallets, mens louis vuitton wallet, women louis vuitton wallet.
Bedrooms are a place for rest and relaxation. The simplicity of modern bedroom designs creates a calmness that makes that feeling even more prevalent, There are funny and strange bedrooms with different shapes .
dupont lighter, dupont lighters, st dupont lighter, s.t. dupont lighters. As classical music evolved, distinctive characteristics developed. Changes in form were seen along with changes in phrase structure.
replica louis vuitton belts, replica lv belts, replica lv belts, Elegant replica louis vuitton belt, Fashion replica louis vuitton belts for men, replica louis vuitton mens belt.
Adjusting your diet to a healthier way of eating is a way to lose belly fat without dieting that works for many people. Instead of putting yourself on a restrictive and often unsafe diet, you can try adjusting the way you eat. Instead of five cookies, maybe have one small slice of low fat angel food cake. Simple exchanges like that will provide you with a way of eating that will keep you healthy your entire life.
armani belt, armani belts, armani belts for men, armani mens belt. The biggest benefit with classic styles is that they’re never trendy. Trendy styles are meant to push the boundaries and draw attention to the garment. A trendy look is meant to make a bold statement and never slips gracefully into the fashion parade.
The replies were numerous and vociferous. Dave Astels poignantly stated that hand-rolling mocks is so 2001!
white iphone 4 available now. It is the best news today.
Mold making is the core business of Intertech (Taiwan). With world level technology, Intertech enjoys a very good reputation for making Injection Mold and Plastic Moldsfor their worldwide customers.
hermes belt, Gucci Man,beltman.
The replies were numerous and vociferous. Dave Astels poignantly stated that hand-rolling mocks is so 2001!
I think you’re one step before realising that “refactoring” is a bunk concept that (poorly) works around bad programming practices.accounting services
Thanks for shareing! I agree with you. The artical improve me so much! I will come here frequently. iPhone Contacts Backup For Mac can help you backup iphone contact to mac.
Can you do a more detailed piece on “micro waypoints,” I think I am getting the hang of testing, but I am still a beginner.
I think that programmers communicate with structure as much as they communicate with names. It’s the body-language of their code.
As a matter of truth, you will find some factors for individuals to decide the value of the rolex watches. In order to get precious rolexes watches for collecting, you’ll want to pay attention to the following aspects. At 1st, you need to judge the amount of the fake rolex. The amount of the Rolex DateJust watches existing in rolex watches the world is crucial. If Rolex Daytona is exclusive, and it has a small amount within the world, Swiss Replica Watch is going to become far more useful replica watches with the development of years. A widespread Discount Watches just isn’t worth to collect. Useful Rolex Day Date are available in tiny amounts. The distinct looks of these designer fake watches are extremely unique. In most models, the face dials generally feature a layered design. This makes the brand genuinely intriguing and attractive. The cheap watches are created from a few of the finest supplies utilized in contemporary Breitling Watches generating. Copy Watches supplies incorporate solid Fake Watches state and refined stainless steel, diamonds, reinforced crystals and other precious stones. In some models, the bracelets consist of a mixture of gold and stainless steel while a much more casual leather band is also available. The Omega Watches of Raymond Weil are mysterious and intriguing on account of the special textured layering of the front faces. Do not buy sport Cartier Watches if you are an office lady. The replica watches are an individual belonging that represents the taste and the style of a person. Imitation Watches will be easy for you if you have already known about yourself well. At last, we bet you can find the ideal women’s replica watches uk for the women in your life as long as you do research correctly.
You can add a variable, confident that behavior won’t change because you haven’t used it yet
Buy $10 Replica Designer Sunglasses with 3-day FREE SHIPPING this is it
Thank you very much for this article and blog.I like its and as to me it’s good job.
Hermes belt store offers high quality and cheap designer belts, please have a look.
There are various kinds of Hermes belts available to match your needs.
Any lady with wholesale beads wedding on the brain will be dropping not so faint hints beside the wholesale jewelry beads way so pay consideration when you’re receiving prepared to pop wholesale pandora beads the query. You can also seem at the jewelry she already owns to get an clue of her chic, especially regarding what type of wholesale fashion jewelry metal she loves. Keep in mind that she will be got up in this ring for the rest of her life so make definite to choose something that suits her personality.
This is a good post. This post give truly quality information.I’m definitely going to look into it. Really very useful tips are provided here.thank you so much.Keep up the good works. Social Network
A bad beginning makes a bad ending. A bird in the hand is worth than two in the bush. A year’s plan starts with
spring. Bad news has wings. Better to ask the way than go astray. By reading we enrich the mind, by conversation we
polish it. Custom makes all things easy. He is not fit to command others that cannot command himself. He laughs best
who laughs last. tiffany and co outlet
Thank you for sharing,it is very helpful and I really like it!
i remember when math was much simpler in early school years where calcualtors had just become very affordable. This seems too complicated.
great article.
internette görüntülü olarak okey oyunu oyna, gerçek kisilerle tanis, turnuva heyecanini yasa.
I love sharing information Thank you :-)
Your post is informative I love it Thanks a lot :-)
I love your post. Thank you :-)
I will always check your website if there is always a new article. Thank you :-)
thank you for posting this SO MUCH.
teri dhadkano ko chulu
Beats by dr dre studio with look after talk in white. extra attributes on Monster Beats By Dr. Dre Pro Headphones Black a specific tri-fold design and design and carrying circumstance which make for compact and uncomplicated safe-keeping when not in use. Beats by dr dre solo .
thanks for the information..It’s good to see this information in your post, i was looking the same but there was not any proper resource, thanx now i have the link which i was looking for my research.
supra footwear store
Oh! Good I have read your topic I’m really super success Written cheap supras shoes…! I believe you’ve made certain pleasant points in the topic likewise supras shoes. I guess you should not stop with this supras for sale; I would like to see more of your submissions vibram 5 fingers.
Would you like to banckup iphone SMS to mac, macBook, macbookPro as .txt files? Now a software iphone SMS to Mac Backup can help you to realize it.
Wow. You can listen to the track right here, and happy divine thoughts about the universe everybody!
as looking the same but there was not any proper resource, thanx now i have the link which i was looking for my research.beats by dr dre beats by dre sale
Thank you for posting. Waiting for updating.New fashion women LV purses AAA with best quality for wholesale on line from China free shipping
Cleanliness is next to godliness Clothes make the man Cold hands, warm heart
Slewing bearing called slewing ring bearings, is a comprehensive load to bear a large bearing, can bear large axial, radial load and overturning moment. http://www.1stbearing.com
The professional design make you foot more comfortable. Even more tantalizing,this pattern make your legs look as long as you can,it will make you looked more attractive.Moveover,it has reasonable price.If you are a popular woman,do not miss it.
Technical details of Christian Louboutin Velours Scrunch Suede Boots Coffee:
Fashion, delicate, luxurious Christian louboutins shoes on sale, one of its series is Christian Louboutin Tall Boots, is urbanism collocation. This Christian louboutins shoes design makes people new and refreshing. Red soles shoes is personality, your charm will be wonderful performance.
A university studentbeats by dr dre caught by the enemy, the enemy tied him at the poles,just beats solo headphones purple and then asked him: say, where are you? You do not say it electrocuted! Scheap dr.dre beats studio headphones balck/yellowtudents back to the enemy a word, the result was electrocuted, he said: I am TVU.Hot sale beats by dr dre pro headphones
http://www.spyderjackets-outlet.net
http://www.arcteryxjackets-sale.com
thanks a lot for sharing. /danielle
Stop data lose on the mobile. So you can export the files to HDD.
Thanks for the information, I’ll visit the site again to get update information video games
Now that I’ve Provided the 1st of my Vegas talks I DesiRed-colored to Article Almost everything On line for Anybody who couldn’t Go to in Particular person.ralph lauren shirts Slides are Right here (OpenOffice Structure)WStrikeepaper is Right here (Pdf file)No.-ME Resource code is…At present kinda ugly.ralph lauren shirtsralph lauren hats If Anybody In fact Would like a Duplicate Allow me know and I’ll Thoroughly clean it up for Launch.217 Ft is the Variety I Arranged; I Think that’s a Globe Report (beating Each the 69 Ft from Flexilis at Defcon 13 and the 65 meters claimed by ThingMagic in a Yahoo Tech Speak). My Gear is capable of Much Extra but I Strike the Restrict of my Variety;
Womens Pony Polo
a chainlink fence a Number of hundRed-colored yards Aside was reflecting the RF Energy, meaning that Extra Energy led to Higher interferenceUsa Style Custom Ralph Lauren will be the Standard outfitter of the US Olympic and Paralympic Clubs for London 2012, Creating the opening and closing ceremony parade uniforms.Ralph Lauren previously Developed the Groups’ uniforms for the 2008 Game titles in Beijing and 2010 Winter Game titles in Vancouver.Ralph Lauren Tees
In Add-on, Ralph Lauren will Design and style a Selection of village Put on Clothing and Add-ons inspiRed-colored by the 1948 Olympic Game titles in London. The vintage motifs will Combine with Modern day styling in Usa Colours of Red-colored, wStrikee and navy and new Olympic Group logo.The Ralph Lauren 2012 Olympic Collection Characteristics reissued heritage pieces from the 1930s and ‘40s, Which includes fleece Cozy-ups, a cricket-Training collar shirt and sweatshirts with United states appliqués.Ralph Lauren Sweaters
Reproductions of Monitor & Area Design and styles Characteristic an updated 1948 crest.If you are in search of nice Dr Dre Beats,our online store will be your first choice. Welcome. The Dr Dre Beats Studio is purchased by a lot of people due to its superior quality and low price. Start your shopping now! The Dr Dre Beats Tour Black is taking a large market now, so buy one at once. We accept paypal. Everybody like this world famous brand Dr Dre Beats Pro because of its finest quality but cheap price. You can order one too. Buy it quickly. More surprise are waiting for you if you order our AAA quality and cheaper price Dr Dre Beats Solo HD. Never lose this opportunity. We can supply you this most people loved Dr Dre Beats In Ear with fast delivery and free shipping. Why don’t you seize this precise chance to change your style by buying our latest Beats Studio Sale. Move your finger to log in. How can you stand still when seeing so attractive Dr Dre Beats Limited? Won’t your heart beat more fast after seeing our eyecatching Dr Dre Beats Sale Online? What are you considering? Rush to purchase!!!!We are waiting for your coming!! Beats Dr Dre are worthy owning. Well-known Dr Dre Beats Studio Black Yellow have the heights range from around the ankle to above the knee, and they are available in different colours. This Beats By Dr Dre .
Functional Refactoring and “You Can’t Get There From Here” 70 good post37
Functional Refactoring and “You Can’t Get There From Here” 71 hoo,good article!!I like the post!157
Intertech Machinery Inc. provides the most precise Plastic Injection Mold and Rubber Molds from Taiwan. With applying excellent unscrewing device in molds,
Intertech is also very professional for making flip top Cap Molds in the world. Mold making is the core business of Intertech (Taiwan). With world level technology, Intertech enjoys a very good reputation for making Injection Mold and Plastic Molds for their worldwide customers.
When it comes to fashion, each and everyone wants to look the best?