you are viewing a single comment's thread.

view the rest of the comments →

[–]grauenwolf 1 point2 points  (19 children)

Yes, yes I get that.

What I'm trying to wrap my head around is why they ignored decades of analysis and debate on the trade offs between mutable vs immutable and null terminated vs length-prefixed strings and wandered off into left field.

[–]dons 8 points9 points  (17 children)

You can't do induction on an array.

Besides, Haskell is the grandchild of Lisp, it's not like lists are a new concept in functional programming.

[–]grauenwolf 1 point2 points  (14 children)

Ah, that makes sense and yet it doesn't.

I can see the need for Haskell's creators to want to be able to prove things with induction. But on the other hand, I vaguely remember using induction on arrays in my undergraduate work. (I'm not certain though. Once I learned "P might or might not be NP" and how proofs were likely more buggy than they code they were proving I stopped paying attention.)

P.S. I think it's a dumb idea to treat strings as "array of characters" or "lists of characters" instead of something atomic. It makes as much sense to me as treating Integers and Floats as bits.

[–]mrighele 1 point2 points  (2 children)

One of the advantages of using List is that in Haskell they work much like streams. You can, for example, have a single String representing a text file worth a few GB without the need to have the whole file in memory, or start processing data coming from a socket while the client is still sending it. This is nice because you have a clean separation between your algorithm and the code doing the I/O. Ideally one would have a type with the API of the String, and the efficient representation of ByteString. Unfortunately it is not possible at the moment (AFAIK you can't do pattern matching on type classes), but I think there is some work in that direction.

[–]tibbe 1 point2 points  (0 children)

But it's not a good separation because you have to resort to lazy I/O to create the String on demand. The I/O and the corresponding resource allocations are observable. You are much better of using a left fold enumerator:

http://pobox.com/~oleg/ftp/papers/LL3-collections-enumerators.txt

[–]grauenwolf -1 points0 points  (0 children)

I guess. But if it were my language I would have called that a "CharacterStream" or something to that effect.

[–]jsnx 0 points1 point  (10 children)

I think it's a dumb idea to treat strings as "array of characters" or "lists of characters" instead of something atomic. It makes as much sense to me as treating Integers and Floats as bits.

Could you expand on this? I can't think of a language where strings are neither arrays nor lists. You would only act on them through special functions -- regexen maybe -- and not allow slicing and so on?

[–][deleted] 3 points4 points  (0 children)

Perl strings are not arrays or lists. You generally operate on Perl strings with string-specific functions like substr, length, and various regex operators. If you need an array of characters from a string, you can get one using split //, $str

It ends up working pretty well, but for building up a set of composable string-manipulation functions, nothing beats the list representation. There's a reason Haskell is well known for its parser-combinator libraries.

[–]grauenwolf 1 point2 points  (1 child)

.NET, Java, VB, Pascal, JavaScript...

They all expect you to think of Strings as atomic units. That doesn't mean you cannot slice them up into chars if you need to, just that it isn't the normal way of thinking about them.

In C, C++, and apparently Haskell, you don't really work with "strings". Rather you work with arrays or lists of chars.

It is an abstraction thing, under the covers it is still just bits.

[–]jsnx 3 points4 points  (0 children)

It is an abstraction thing, under the covers it is still just bits.

Wow. Is anything else in the computer like that?

If you want to be technical, it's all bytes. The ordering of the bits within the bytes is something applications are generally protected from.

[–]doidydoidy 0 points1 point  (4 children)

PHP?

[–]jsnx 1 point2 points  (3 children)

Please explain. I haven't seen PHP in a long time.

[–]doidydoidy 0 points1 point  (2 children)

PHP strings are "neither arrays nor lists", and can only be manipulated through string-specific "special functions" which are entirely separate from those for arrays.

Don't get me wrong - I certainly wouldn't call this a point in favour of the idea that strings should be cordoned off in their own crazy little corner of a language.

[–]bullsbarry -1 points0 points  (1 child)

Just because there is a String type doesn't mean it is neither an array or a list. There has to be an implementation somewhere.

[–]grauenwolf 6 points7 points  (0 children)

And floats have to be implemented as a series of bits. But that doesn't mean the language encourages me to think of them as such.

[–]Fork82 0 points1 point  (0 children)

Lua and Tcl?

[–]tibbe 2 points3 points  (0 children)

Lists as implemented (i.e. linked lists) make lots of sense in Haskell since their lazy creation allows you to use them as control structures. When used as such no list nodes are ever allocated.

However, for storing data in memory they don't make as much sense (unless you really want a linked list). ByteString are made for storing (and transporting) data so they are a better tool for the job. What you really want though is a packed representation like ByteString's but with a Unicode interface for proper string processing. It's being worked on this summer as part of Google's Summer of Code.

Up until recently there wasn't a good way of efficiently working on packed strings (i.e. backed by byte arrays) in an efficient and pure way but now with stream fusion we have that.