Which string to use? String, ByteString or Text or something else? How to convert between zillions of String types, which are, it seems, completely incompatible even though providing similar functionality? So much for the support of abstraction.
Which library is good for doing X? It seems, like String, the Haskell provides too many experimental and/or incompatible and/or immature libraries to do many trivial things.
Then there are issues of laziness combined with IO and you get a `seq` shenanigan.
Then there are issues of laziness combined with inability to profile/debug and you get a `analysis` shenanigan.
Then there are issues of laziness combined with inability to handle exceptions without great grand-daddy-catch-all-bad-things IO monad and you get a `IO monad exceptions` shenanigan.
So, there are a lot of Haskell shenanigans, too. Take your pick.
In fact, I have learned a lot many good programming practices/principles by spending time to learn Haskell. I do apply some of those in my projects in other languages.
A lot of the problems I encountered probably boiled down to inexperience on my part, and perhaps not understanding idiomatic ways of doing things in the language. But another part of it is that I think the community has not settled on a set of common idioms.
There are things about Haskell that I absolutely love. The expressiveness is amazing. Chaining a monadic sequence can feel magical at times. Treating errors as just values is nice. But what do you do when the libraries that you depend on throw exceptions instead of using Either?
And those awful compiler errors can be so, so frustrating. But I will return to you again one day, dear Haskell.
The issue is when this monad is actually a monad transformer tower, in which case there is actually a bunch of "magic" happening at each line.
File a bug on them
tome's response is amusing, but assuming you need to keep getting work done and aren't interested in forking the library...
You wrap the library in a shim that forces the return values, catches anything that's thrown, and returns Either. If it's a library that you only use in one or two places, that shim might be inlined.
There's strict and lazy ByteString, which you should use whenever you're working with buffers of bytes that don't have any associated encoding and aren't text.
There's strict and lazy Text, which you use for human-readable text that's decoded from some specific encoding, like ASCII or Unicode.
There's String, which you use when interacting with an API that requires use of String, like anything in the language standard.
It's certainly some amount of complexity, but it's not anywhere near as complex as I keep seeing claimed, unless I'm missing something. It's certainly ugly that we still have to deal with String, and that's a notable wart on the language, but I rarely even think about it.
One guess I've had about part of the confusion is that ByteString has the word "String" in it, which might make people assume that it's for text. A better name would be "Buffer" or "Bytes". I've also speculated that maybe part of the complexity is having to explicitly encode and decode to get Text, instead of the implicit coercion you get in other languages that freely mix bytes and text.
If you want a greatly simplified way to unify string conversion, you can use string-conv. https://hackage.haskell.org/package/string-conv-0.1/docs/Dat...
Edited to add: it's been pointed out to me that "zillions" might not have actually been a claim that there's enough string types actually keep track of them, but is probably just hyperbole to express some frustration. If that's the case, my apologies for my failure at reading comprehension.
Python got to two, and the community decided that was enough of a PITA to merit a breaking change in the language in order to get back down to one. C++ also has two, but we put up with it because it's C++ so really we're just thankful it's not three or four.
Five is so far beyond the pale that it is absolutely reasonable to hyperbolize it as "zillions".
Treating all bytes as if they happen to accidentally represent utf-8 encoded unicode text would be a big mistake; there's significant advantages to representing text and byte buffers separately. They are very different things.
Choosing to support only strict or only lazy handling of byte buffers or text would be quite unfortunate; there are significant advantages to both for different algorithms and use cases, and encoding the difference in the type system seems entirely reasonable to me.
I'm curious which of these you disagree with. Would you prefer that Text and ByteString be merged into one data type, so that the compiler doesn't consider it a mistake to treat arbitrary bytes as if it were text without specifying any encoding? Would you prefer that Text and/or ByteString discard support for lazy representation, or for strict representation?
http://www.suspectsemantics.com/blog/2016/03/27/string-types...
I would say it's actually justified in that.
If one considers those to be string types, then Vec<u8>, Vec<16>, and Vec<32> would be considered string types as well (in addition to both fixed-size arrays and unsafe pointers to the same).
All the other types provide specific functionality that you won't get otherwise. (While String is there only because it is easy to use.) If you really don't care about that extra functionality, just keep with strict Text, and be done with that.
Now, if the perfect number of string types is 1, why couldn't you name any language with that number. By the way, Java also has two string types, as does .Net. Python still has 2 types, they just don't coerce into each other anymore, and I've probably seen a dozen C++ string types already.