242 karma · joined January 29, 2016
Blog: https://funwithfunctions.com
For me though they really come into their own when those types then help to eliminate boilerplate. Haskell's foldMap function is my classic example of handling the accumulation of a result where it does the hard work based on the types. Idris goes even further by supporting the ability to infer obvious code for your code editor like handling each case in a sum type.
How many regular users do neither of these things and just shove their old phone in a drawer or let their kid watch YouTube on it?
Exactly, why is a page needed in the first place? I'd bet more than 99% of users don't even have a clue that exists or even know about the underlying problem.
Oddly now I find it really legible compared to other languages, you can still make things obtuse if you really want to, but the flow seems so much clearer.
I would say compared to Java (as you mentioned it) there's much less separation because things invariably gravitate towards big balls of mud containing lots of state. But in Haskell the function you're looking at is only tied to the functions and data types it uses, no more, no less.
- Slow compilation, I think even now immutably concatenating a handful of strings makes the compile time exponential.
- Over reliance on keywords and special case syntax, magic doesn't compose. A bunch of it just supports Optional for example.
- Xcode, nuff said.
- Equatable and Hashable for tuples were implemented with invisible compiler magic, so they wouldn't work with generics.
- Variance is hot garbage, it has variance, but no way to control it.
- No higher kinded types, so useful FP abstractions become a chore to implement.
- I regularly had compiler crashes on comparatively simple code.
- Sometimes absolute nonsense compile errors pointing at random parts of my code.
- SourceKit didn't handle basic stuff like type aliases.
Going on the various things I've seen since we switched our project to JavaScript from Swift it looks like the keyword soup has gotten worse.
However it also adopts a bunch of the bad parts like having variance but not really having a way to handle it. Last I remember the Equatable instance for tuples was just magic, it was impossible to rely on it with the types. Even maybe 6 months ago when I last tried this if you write some code that appends maybe 6/7 arrays together immutably the compiler would go into an exponential spin.
The project I'm working on ending up dumping it entirely and moving over to being a web project written in TypeScript because it was so bad. Part of that being a laundry list of problems with the surrounding tooling like SourceKit which may or may not still apply.
There's definitely a bias towards the familiar however, it took me a while to get my head around the "FP way" as it were. The frustrating thing is that like you say most people are just trained in procedural programming with often at most minimal contact with anything functional which causes a kind of pressure on the whole industry.
Swift is probably one of the worst examples when it comes to functional programming because it's still a C like language with some FP like things in the stdlib. So you get none of the advantages and some inconsistencies weighing it down.
Now if I could use Haskell in Unity3D then I'd get hella excited, but there's a lot more barriers there methinks.
It suffers from similar problems to Scala, where it tries to blend OO concepts in with FP concepts. Variance is where this flares up terribly because it doesn't provide any explicit support for covariance or contravariance. You end up with invariance and subtyping in a bunch of places which is not a nice combination.
Protocols like Equatable and Hashable are implemented with compiler magic for arrays and tuples. Which means that you run into trouble with generic functions that say accept two instances of the same type which is Equatable if you pass an array of ints. The underlying reasons behind this (which mostly escape me at midnight on a Sunday) are something to do with protocols on generic types. You can't say "for a List if the elements are Equatable the List is equatable" IIRC. This one annoys me no end as we've had to fudge our way around it several times on the same project.
For some reason that eludes me, Optional<T> is given all sorts of special case syntax ("if let" and "guard let") which is like a crap version of "for yield" from Scala or do notation in Haskell that only works on that. As a result a lot of convenient abstractions are just not possible you end up writing all kinds of horrid looking chained map/flatMap calls instead. Sometimes because of this dissonance between things a block of code might have a guard let block, then some other stuff, then an if let block with an else condition. Whereas if you wrote the same thing in Haskell it would be one do block and that's it.
Concurrency and parallelism support is effectively Grand Central Dispatch, which is the most imperative API ever on macOS/iOS and on other platforms (according to the Github page I just looked at for it) is in the early stages of development. You're just calling the old Objective-C API and the language doesn't help at all there.
Edit: As a bonus addition, it's a statically typed "FP" language which doesn't have higher kinded types which means a bunch of handy abstractions are a real pain. See the Swiftz project for how they have to define things like monads as an example.
Is that enough problems?
Simple things like "a + b +...+ n" cause compile times to balloon exponentially, which means for arrays you end up refactoring concatenation of immutable arrays into a mutable array you call appendContentsOf on a bunch of times.
SourceKit on the surface sounds great, but in truth it's a simple text parser that doesn't understand type aliases for example.
The compiler _really_ struggles with anything beyond very simple generics, first the type inference starts to fail and then it'll refuse to compile until you break the code apart and add type ascriptions.
The compile errors are often absolute nonsense, pointing nowhere near the actual errors or are like the Magic 8-ball coming up "ask again later".
The project I'm working on has been a mix of Swift and JavaScript, we're happily increasing the ratio in favour of the latter because of all the pain we've had with Swift. I personally don't even like JavaScript but it's not even a contest between the two.