All this does is pull a list of "spot instance" prices from AWS EC2, sort them and filter them. I rewrote this from a python script that became too complex.
The last time I looked at Haskell, it needed ~700MB of dependencies before I could even get started.
Edit: Clojure looks like a good way to start, although https://github.com/mrowe/clj-aws-ec2 isn't really complete.
ghc is big, indeed. There are smaller alternate compilers and interpreters (that no one uses). Compiled executables are usually smaller than ghc, which is probably the biggest Haskell programs ever written.
So for example, here you could make a nice little EC2 DSL that would get your stuff (for the actual Haskellers: Free Monad):
spotPrices :: Region -> EC2 [SpotPrice]
spotPrices = GetSpotPrice -- DSL Leaf, executed by runEC2
spotPricesForAllRegions :: [Region] -> EC2 [SpotPrice]
spotPricesForRegions regions =
concat <$> MapM spotPrices regions
Your spot price update function becomes something even simpler now: runEC2 :: EC2 a -> EC2Config -> IO a
runEC2 = stuff -- this is where you call whatever EC2
-- lib is available
updateSpotPriceFile :: [Region] -> IO [SpotPrice]
updateSpotPriceFile regions = do
spotPrices <- runEC2 (spotPricesForAllRegions regions)
(myEC2Configuration)
writeToFile (toJSON spotPrices) "spotprices.json"
return spotPrices
I'm not going to port all of it, but with a more functional version you could avoid having to keep on making EC2 clients all over the place, and you could keep your config in one place.The problem is that it's pretty obtuse if you don't know the right design patterns. There's a myth in FP circles that design patterns are for OOP only ("we have functions, we don't need observer patterns!"), but it's a myth. But if you get good, you can write some pretty concise code + get all the goodies.
Haskell has the whole GHC thing, and also the issue of lack of good library documentation (or lack of libraries on certain stuff)...
Also recursive functions tend to spiral out of control and have ridiculous exponential run times.
Recursion has nothing to do with stack traces. Stack are one way to implement some version of recursion in functions.
Some other versions of recursion in functions can be implemented with loops.
And, of course, not only function can be recursive, but data structures as well. (And a few other things.) You can traverse these data structures any way you feel like.
> It's difficult to debug and follow the code around, or even to understand the code if someone else wrote it.
I have that problem with loops (and mutation) much more than with recursion. Different things make different people's heads hurt.
> Also recursive functions tend to spiral out of control and have ridiculous exponential run times.
Oh, that's an artifact of how you've been taught (or self-taught). Loops are a special case that only works well for simple tasks. Recursion is more general and can express the simple case in a simple way.
Of course, if you only reach for recursion in the complicated cases, all uses of recursion you see will be complicated. Simple observation bias.
As someone who also has visited that dark and twisted land... I completely agree with you (every post in this thread).
I don't think I ever once experienced the supposed benefits.
If you have exponential run times, I don't think tail call optimization would help you.
Of course, that claim with the exponential run time in the first place is ludicrous: sure, you'll have a hard time implementing the Ackermann function with loops. But that's a problem with loops, not with function calls.
I say function calls here, because recursion in function is just a special case of function calls. You gotta have functions in a modern language in any case, so recursion comes for free. No need to introduce another concept like loops and clutter up your language.
I also disagree wrt it being more difficult to debug, understand, etc. Your mileage may vary here.
Second, functional programming usually emphasises combinators like map, filter, reduce/foldr. Those are easier to read than either naked recursion or loops.
In theory. In the actual world, loops are how we're used to think about doing N things.
For anyone else---normal people without programming experience, or programmers trained in different paradigms---loops are not special.
Of course, we mostly talk about programmers here, and imperatively trained programmers are in the majority.
In any case, lots of languages have gotten map and filter, and people seem to adapt to them just fine. We just have to wait another decade for the more interesting combinators to trickle down.
No, we refers to both "imperatively trained programmers", and, more especially, laymen.
>For anyone else---normal people without programming experience, or programmers trained in different paradigms---loops are not special
I very much doubt any layman who does anything repetitive (e.g. runs 10 laps) thinks of it as recursion as opposed to keeping a mental index and thinking it similarly to a loop (without knowing the terminology of programming of course).
>In any case, lots of languages have gotten map and filter, and people seem to adapt to them just fine.
Those are just abstracted loops though, not recursion.
> Those are just abstracted loops though, not recursion.
Map and filter on a tree is about as recursive as it gets. Loops are the special case of recursion that does work well on linear data structures like linked lists and arrays, yes.
We may think "do this operation to all the things I have" for things that involve the totality of some items as an unknown number (e.g. pack all clothes, take all dishes out of the dishwater).
But we also think with indices, and very intuitively, for anything involving a specific number of counts, like the example I gave (run 10 laps, I've run 1...5...7...8...10, done).
>Map and filter on a tree is about as recursive as it gets.
Well, the original comment was "lots of languages have gotten map and filter, and people seem to adapt to them just fine."
And while this might be true for array like collections, I don't think people have adapted 'just fine' to map and filter on trees -- I very much doubt it's commonly used at all.
Counter-anecdote:
Oh, if people were good with indices, they wouldn't have so much trouble with ordinals vs cardinals vs nominals.
> And while this might be true for array like collections, I don't think people have adapted 'just fine' to map and filter on trees -- I very much doubt it's commonly used at all.
Python's set and dictionary comprehension encapsulate map, filter and cartesian product. But that might strengthen your point: Python goes to great lengths to make these look like loops.
I guess we need to get a large number of ordinary people and do experiments on them.
But, hey, even C++ got lambdas.