This is not true in my personal experience.
As has been famously said (paraphrased): Functional programming makes tough problems easy and easy problems tough.
In other words the value of functional programming depends on your domain.
This is not true in my personal experience.
As has been famously said (paraphrased): Functional programming makes tough problems easy and easy problems tough.
In other words the value of functional programming depends on your domain.
They are also a lot less productive. It depends entirely on what you are doing.
That needs a qualifier: it can make easy problems tough if you're not familiar with how to solve them in a functional context.
A big part of that is because smart people have already solved the tough problems and made them available as language features or libraries.
All problems are easy if you are familiar with how to solve them. Unfortunately it's part of the problem to find out how to solve them, and that can be unusually hard in case of functional programming. Like solving something with recursion instead of loops + states. There is a reason cookbooks use loops not recursion.
My favorite example of this is implementing quicksort. It's significantly easier in C than it is in Haskell.
Oh please, what's so hard about
qsort :: Ord a => [a] -> [a]
qsort [] = []
qsort (p:xs) = qsort lesser ++ [p] ++ qsort greater
where
lesser = filter (< p) xs
greater = filter (>= p) xs
:)folks, take that with a big ol /s, you would never want to actually use that algorithm. But the real deal isn't all that awful: https://mmhaskell.com/blog/2019/5/13/quicksort-with-haskell
where
(lesser, greater) = partition (< p) xs
I just learned about the existence of this function today, and wonder why I had never seen it used before.https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-...
The pragmatic way to look at Haskell is not that it's purely functional, but rather, you could write <del>imperative code</del> Monads if you wanted, and that gives a "functional by default" environment, whereas most imperative languages default to mutable objects etc that are not friendly to functional-style programming.
But then the more modern languages are catching on with immutable by default variables etc. so in the end the differences between newer languages may not be that great after all...
So, one of the best sorting algorithms ever devised is not actually usable to sort a [a] in Haskell... I maintain this is a good example of making an easy problem tough.
Haskell uses many different collection types, just like any other language. Why not?
> it's actually even slower than the original not-quicksort implementation above, because it actually has to make a copy of the original list, and then return a copy of the mutated array.
Sure, but it could also not do that, if callers are happy to provide a mutable array, just like any other language ...
> one of the best sorting algorithms ever devised is not actually usable to sort a [a] in Haskell
Indeed! One of the best algorithms for sorting a mutable array can't be used on an immutable data type, just like any other language ...
None of this invalidates your original claim that "It's significantly easier in C than it is in Haskell" of course.
I'm not a cheerleader for Haskell, it's not the most appropriate language for every job (certainly not for quicksort). But some folks suddenly become hyper-optimizing assembly programmers whenever anyone has the thought of porting a sql crud app to another language... Horses for courses and all that.
And because of mutual recursion, that means that tough is easy (and easy tough). In other words, if we call the class of tough problems T and easy problems NT, we have T==NT, given FP.
If you try and turn F# into Haskell at home you may run into that problem.
F# is functional first language so if an object oriented or procedural solution is the right call the options right there when you need it.
Even in Haskell, which tries to control side-effects more, it's not hard; it's just that it's stuck with an "IO" annotation. Any function that calls an IO function also becomes an IO function; it's infectious.
main :: IO ()
main = putStrLn "hello, world"One way of viewing Haskell is that you are lazily constructing the single composite "effect on the world" called main.
helloWorld :: IO ()
then is a value representing an effect, but it only actually happens when it becomes a part of main.Threads complicate this but don't completely destroy the model.
Edit: Eh, I thought it was a fun quip.
Hello, world!