![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
http://cdsmith.wordpress.com/2007/07/29/37-reasons-to-love-haskell-playing-off-the-ruby-article/
You don't really need to even click that, do you?
Well, maybe you do... Basically there's a "37 reasons to love Ruby"
article, so this guy did a copy for Haskell. While I applaud this, some
of the "facts" are rather dubious...
#3. "It's dynamic. Lots of Haskell applications feature dynamic code
loading." Er, yeah... if you have the damned compiler installed! What
you *can't* do is compile a module and then dynamically link it in
later. You *must* have the actual compiler available. And it's _very_
hackish and awkward to get it to work. It's not a compiler feature, it's
a low-level C library that somebody hacked together which sort-of works.
It's a nightmare to use it though!
#6. "It's multi-platform." Yeah, but unfortunately the Windows version
is running under Cygwin using the GNU toolchain (e.g., GCC, GAS, LD),
and almost all libraries involving binding to a C library spectacularly
fail to compile on Windows. All the APIs are fairly POSIX-centric so you
generally can't access Windows-specific functionallity. And so forth.
#8. "It's innovative." Well, perhaps. I love the way he cites a whole
bunch of features and "these are rare in other languages". Er, but *all*
the features you cited are features of the type checker! :-P (Why not
mention, say, concurrency and parallelism?)
#10. "It has a smart GC." Er... looks pretty primitive compared to
Smalltalk, actually.
#11. "It's a scripting language." You have *got* to be kidding me! Sure,
many things in Haskell are one-liners. But typically anything that
involves talking to the outside world has lots of small but fiddly
details that take heaps of code to sort out. Hardly a nimble scripting
language!
#15. "It's intuitive." Hahahaha... nice! (The argument does kinda make
sense - the learning curve is steep because you really do have to learn
new stuff, not just new syntax for doing the same old thing. And the
Haskell syntax is as intuitive as it can be considering that. But
still... stretching it a little, eh?)
#16. "It handles exceptions well." You... have... GOT to be kidding me!
If you try to read a non-existent directory, there is *no way* to
distinguish from a "this filename is invalid" error and a "this file
doesn't exist" error and a "there was a hardware error" error. (You
*can* at least distinguish "access denied".) Asynchronus errors are a
nightmare with lazy evaluation too!
#17. "It has advanced array types." Ha...haha...hahahaha! You've got to
be kidding me! The API is *horrid*! There is mile after mile of
functionallity missing. And there are all kinds of inconsistencies in
function names, etc.
#25. "It pays attention to details." I can't even determine what the
hell he's talking about here...
#27. "It has a rich set of libraries." Oh come *on*!! You cannot be
serious! That ball was on the line! Er, I mean... Haskell lacks
libraries for just above every possible task you can name! Want to read
a GIF file? Sorry, can't do that. Want to send a PGP-encrypted email?
Sorry, no SMTP support, no PGP support. Want to compute a CRC32
checksum? Sorry, no library for that. Want to play an AVI animation?
Guess what? No library.
But best of all: What libraries do exist do *not* work on Windows. Ever.
There are 12 database libraries, and none of them compile on Windows.
There's a wxWidgets library - doesn't run on Windows (in spite of the
special Windows-specific setup routine). There's a libSDL library... can
you guess? Doesn't work on Windows.
Haskell - Great language, just don't try to communicate with anything.
#28. "It has a debugger." Finally. It took long enough. And it's a ****
to use.
Overall though, I still thing Haskell is a great language. But then we
have this:
http://intoverflow.wordpress.com/2009/01/13/why-haskell-is-beyond-ready-for-prime-time/
Reading this, you'd think Haskell has the most awsome tools EVER! Sadly,
it's not true...
"Availability of quality libraries"
Only on Linux. And even then with huge gaps. And the overwhelming
majority of libraries were once somebody's one-man project, and lay
long-forgetted. And most of them utterly lack any documentation at all.
Oh, and Hackage is really quite clunky to use.
"Project Management"
Setting Haddoc up in such a way that it works properly is seriously
hard. (OTOH, it now comes with the compiler, which should radically
improve this!)
GHC is "the most advanced compiler anywhere", is it? Sure, I'm
enthusiastic about it, but this seems over the top to me.
(E.g., you can't compile different parts of the same program with
different versions of the compiler. Therefore *all* libraries must be
shipped in source-code form because the compiled versions only work with
one release of the compiler. Not so "advanced" now, eh?)
"Technology"
"[Haskell] stands alone in its simultaneous support for many language
another 10 years."
better support for concurrency than any other language[...]"
Wow, calm down there partner! Let's not get carried away here. Haskell
is an impressive language, but I'm sure somewhere there's something that
beats it in functionallity terms.
"To get a sense for how wildly amazing Haskell-related technology, check
Except that it doesn't work. Nice try though...
"Community"
"Lastly we come to one of the most special features that Haskell offers:
its unique developer community."
I really can't comprehend where this myth that Haskell has a great
community keeps comming from. It isn't true!
If you ask an easy question, you will get 200 replies before you can hit
the send/receive button. If you ask a hard question, or a less
interesting one, you get silence. And if you *dare* to suggest that
calling something an epimorphism is a bad idea, you'll get flamed off
the planet!
Sure, generally the people are quite friendly. This is hardly unique to
Haskell though. The POV-Ray community has always been quite friendly,
but you don't find them calling themselves "unique".
very special. Every day there are new developments in the community that
push the boundaries of technology, enabling people to write
sophisticated programs in less time and with greater reliability. There
have somehow been gifted to us today."
Again, I don't think Haskell has ever done anything that can be called
truly "ground-breaking". If anybody knows different, let me know...
- We didn't invent pure-functional proramming with lazy evaluation and
automatic type inference. (Indeed, Haskell was designed because there
were already *too many* such languages, and they wanted to replace them
all with just one.)
- We didn't invent curried functions, high-order functions, maps and
folds, and all the other high-tech stuff that abounds in Haskell. This
stuff appears in any half-decent functional language. (E.g., I imagine
Lisp probably did it years before us.)
- We didn't invent algebraic datatypes. Those existed for decades before
us. (Although they're fairly rare in real programming languages.)
- We didn't invent type classes. It's an unusual feature, but it was
around long before Haskell.
- We didn't invent monads either. We borrowed them from category theory.
- We certainly didn't invent parallelism annotations. (As I understand
it, even languages as backward and retarded as C have those now.)
- We didn't invent Software Transactional Memory either. That was an
idea that researchers thought was cool, and it eventually got borrowed
by Haskell.
- We didn't invent Nested Data Parallelism - that's another exciting
research project somebody else did years ago that recently got
integrated into Haskell.
Indeed, I'm having trouble finding anything that Haskell itself actually
created or perfected. Arguably we have the best G-machine
implementation, but all that means is we have a compiler that produces
fast code. It's not a language feature.
Even more amusing are some of the comments:
- There's no IDE for Haskell, but "I don't think an IDE is really
necessary". Well *sure* you don't. Because you haven't got one yet! :-P
- Some guy rightly complained that you can't [easily] define two
datatypes which have fields with the same name. This is obviously a
pretty silly limitation. I love the reply "but that's good though". Uh,
yeah, lotta logic there.
- Most significantly: "Haskell will be 'ready' for 'the real world' when
we start seeing real, large-scale applications written with it. Until
then, nobody is going to care." I think this just about sums it up,
really...
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 wrote:
> I really can't comprehend where this myth that Haskell has a great
> community keeps comming from. It isn't true!
>
> If you ask an easy question, you will get 200 replies before you can hit
> the send/receive button. If you ask a hard question, or a less
> interesting one, you get silence. And if you *dare* to suggest that
> calling something an epimorphism is a bad idea, you'll get flamed off
> the planet!
Well sit on my head and call my Harley... it seems there are people
ralleying to my latest call for less opaque terminology! o_O
I guess I'm not as hated as I thought...
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 wrote:
> #25. "It pays attention to details." I can't even determine what the
> hell he's talking about here...
I can give you examples of what "paying attention to details" means. Dunn
o
if it's the sort of thing this guy's talking about, but...
Remember a decade ago, when people were making scripting languages
implemented in C? Lots of those languages had strings that were,
internally, null-terminated. But since they were also GCed, you didn't ge
t
the memcpy/memset sorts of functions, only the strcpy sorts of functions,
so
you couldn't actually work with binary data in a string.
And then they'd have stuff where a string literal starting with a zero is
octal. And someone would read a string from a form or the keyboard or
whatever that's supposed to be a postal (zip) code, and the user would ty
pe
09375, and the program would barf, because 9 isn't a valid octal digit.
Using a leading 0 to always mean "octal" only works if you have source co
de
compiled separately from the user input.
Working around this sort of lamebrainness is necessary if the language
designers don't pay attention to detail. (These are both examples from Tc
l,
incidentally. :-)
> "To get a sense for how wildly amazing Haskell-related technology, chec
k
> out Automatic generation of free theorems — a tool that, given
a
> function’s type signature, can *write a function for you that h
as the
> correct signature!* You won’t find this kind of thing anywhere
else."
Aren't there lots of functions that have the same signature? I mean, wha
t's
it going to write for
f :: [a] -> (a -> Bool) -> [a]
> - We didn't invent algebraic datatypes. Those existed for decades befor
e
> us. (Although they're fairly rare in real programming languages.)
Do you actually have algebraic datatypes in Haskell? Kewl.
> - There's no IDE for Haskell, but "I don't think an IDE is really
> necessary". Well *sure* you don't. Because you haven't got one yet! :-P
Heh. Funny how that works, isn't it?
--
Darren New, San Diego CA, USA (PST)
Why is there a chainsaw in DOOM?
There aren't any trees on Mars.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> Orchid XP v8 wrote:
>> #25. "It pays attention to details." I can't even determine what the
>> hell he's talking about here...
>
> I can give you examples of what "paying attention to details" means.
> Dunno if it's the sort of thing this guy's talking about, but...
>
> Remember a decade ago, when people were making scripting languages
> implemented in C? Lots of those languages had strings that were,
> internally, null-terminated. But since they were also GCed, you didn't
> get the memcpy/memset sorts of functions, only the strcpy sorts of
> functions, so you couldn't actually work with binary data in a string.
>
> And then they'd have stuff where a string literal starting with a zero
> is octal. And someone would read a string from a form or the keyboard or
> whatever that's supposed to be a postal (zip) code, and the user would
> type 09375, and the program would barf, because 9 isn't a valid octal
> digit. Using a leading 0 to always mean "octal" only works if you have
> source code compiled separately from the user input.
>
> Working around this sort of lamebrainness is necessary if the language
> designers don't pay attention to detail. (These are both examples from
> Tcl, incidentally. :-)
Um... ouch! o_O
> Aren't there lots of functions that have the same signature? I mean,
> what's it going to write for
> f :: [a] -> (a -> Bool) -> [a]
Logically speaking, given a function and a list, you can either do any
of the following:
- Throw an exception. (And function with any type signature can do that!)
- Ignore the arguments and return an empty list.
- Ignore the function and return the input list.
- Rearrange the elements of the list and return that.
- Apply the function to the list in some way to decide which elements to
return.
Actually, both "filter", "takeWhile" and "dropWhile" have almost exactly
the type signature above, and they do different jobs. (One filters on
the condition, the others filter "runs" of elements matching it [or not].)
>> - We didn't invent algebraic datatypes. Those existed for decades
>> before us. (Although they're fairly rare in real programming languages.)
>
> Do you actually have algebraic datatypes in Haskell? Kewl.
Um... yes?
data Either x y = Left x | Right y
There you go. That's a sum type of product types, i.e. an algebraic data
type. (ADT - not to be confused with *abstract* data type...)
>> - There's no IDE for Haskell, but "I don't think an IDE is really
>> necessary". Well *sure* you don't. Because you haven't got one yet! :-P
>
> Heh. Funny how that works, isn't it?
Much like the "Haskell doesn't need a debugger because programs work
correctly first time". Until we got a debugger... and now it's "hey, we
have a debugger!"
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Orchid XP v8 wrote:
> Um... ouch! o_O
You learned to work around it, just like any other language limitation. You
occasionally got caught once or twice, then figured it out.
> Logically speaking, given a function and a list, you can either do any
> of the following:
Right. I was asking what code it generated given a signature.
>> Do you actually have algebraic datatypes in Haskell? Kewl.
>
> Um... yes?
> data Either x y = Left x | Right y
Oh, OK. Can you do something more complex, like say a stack?
Hmmm... Maybe essentially all user types in Haskell are ADTs, and I just
never thought of it that way before?
> (ADT - not to be confused with *abstract* data type...)
ADT used to mean "abstract data type", until OO started calling objects
that, and they had to change the terminology. :-)
> Much like the "Haskell doesn't need a debugger because programs work
> correctly first time". Until we got a debugger... and now it's "hey, we
> have a debugger!"
Oddly enough, a lot of projects created by nerds are like that.
--
Darren New, San Diego CA, USA (PST)
Why is there a chainsaw in DOOM?
There aren't any trees on Mars.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
>> Logically speaking, given a function and a list, you can either do any
>> of the following:
>
> Right. I was asking what code it generated given a signature.
And I was just agreeing that more than one function has that type.
However, the website says:
The theorem generated for functions of the type
f :: forall a . [a] -> (a -> Bool) -> [a]
in the sublanguage of Haskell with no bottoms is:
forall t1,t2 in TYPES, R in REL(t1,t2).
forall (x, y) in lift{[]}(R).
forall p :: t1 -> Bool.
forall q :: t2 -> Bool.
(forall (z, v) in R. p z = q v)
==> ((f x p, f y q) in lift{[]}(R))
The structural lifting occurring therein is defined as follows:
lift{[]}(R)
= {([], [])}
u {(x : xs, y : ys) |
((x, y) in R) && ((xs, ys) in lift{[]}(R))}
Reducing all permissible relation variables to functions yields:
forall t1,t2 in TYPES, g :: t1 -> t2.
forall x :: [t1].
forall p :: t1 -> Bool.
forall q :: t2 -> Bool.
(forall y :: t1. p y = q (g y))
==> (map g (f x p) = f (map g x) q)
I have absolutely *no clue* what the hell any of that means. But try it
yourself here:
http://linux.tcs.inf.tu-dresden.de/~voigt/cgi-bin/ft/ftonline.cgi
>>> Do you actually have algebraic datatypes in Haskell? Kewl.
>>
>> Um... yes?
>> data Either x y = Left x | Right y
>
> Oh, OK. Can you do something more complex, like say a stack?
>
> Hmmm... Maybe essentially all user types in Haskell are ADTs, and I just
> never thought of it that way before?
Indeed, all Haskell types are ADTs. Except things like integers,
arguably. OTOH, you could claim that Integer is defined as
data Integer = 1 | 2 | 3 | 4 | ...
As for "like say a stack", I'm not really sure what you mean.
>> Much like the "Haskell doesn't need a debugger because programs work
>> correctly first time". Until we got a debugger... and now it's "hey,
>> we have a debugger!"
>
> Oddly enough, a lot of projects created by nerds are like that.
I wonder if this is why Linux doesn't "need" a defrag tool?
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> I have absolutely *no clue* what the hell any of that means. But try it
> yourself here:
That makes sense except to the extent that I don't know what LIFT{[]} means.
> Indeed, all Haskell types are ADTs. Except things like integers,
> arguably. OTOH, you could claim that Integer is defined as
>
> data Integer = 1 | 2 | 3 | 4 | ...
An abstract data type has to define the operators also.
> As for "like say a stack", I'm not really sure what you mean.
Well, an ADT has to define the type in terms of the operations on that type,
not in terms of a list of values/literals. So the ADT for "Either" would be
something like
Left (Left x) = x
Right (Right x) = x
where the first word in each is a function call and the second is a data
constructor.
A stack is usually defined as something like
new :: -> Stack // Give me a new stack
empty :: Stack -> Bool // Tell me if stack is empty
push :: (Stack, Value) -> Stack // Give me a new stack with the value pushed
pop :: Stack -> Stack // Remove value from top of stack
top :: Stack -> Value // Tell me what's on top
empty(new) // New stacks are always empty
not empty(push(S, V)) // Nothing with something pushed is empty
S = pop(push(S, V)) // pop is inverse of push on all stacks for all values
V = top(push(S, V)) // top returns most recent thing pushed
// And I think there's one other rule you need to make it work, but
// I forget what it is. I could look it up if you care.
// It might involve showing that top(new) and pop(new) are bottom.
In other words, for an ADT, there is no indication at all of the
representation of values. The value of the stack with 1, 2, and 3 pushed is
actually
push(push(push(new,1),2),3)
and not some list expression. *That* is an ADT.
The advantage is that you can prove things about the behavior without
understanding what it's "supposed" to do. For example, you can see it's
impossible to pop an empty stack, or to look at the top element of an empty
stack, because there's no matching expression for top(new). You can also do
things like prove you've covered all the possibilities, prove that one ADT
is a superset of another, and so on.
> I wonder if this is why Linux doesn't "need" a defrag tool?
That and a number of other things like that, methinks. I wasn't trying to
turn it into a Linux bash, tho, since a lot of other environments do this too.
--
Darren New, San Diego CA, USA (PST)
Why is there a chainsaw in DOOM?
There aren't any trees on Mars.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
> I wonder if this is why Linux doesn't "need" a defrag tool?
It depends on what you do to your disk.
The problem is that *if* you get it fragmented (which seems to be less
likely on Linux than on Windows, but still), there is no defragmenter tool
you can use...
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Invisible wrote:
>
> I wonder if this is why Linux doesn't "need" a defrag tool?
It's not a about Linux, it's about filesystems. How many times you have
actually managed to measure any benefit from defragging NTFS partition?
-Aero
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Eero Ahonen wrote:
> It's not a about Linux, it's about filesystems. How many times you have
> actually managed to measure any benefit from defragging NTFS partition?
I have, in very rare cases. But that's when I've created a file in a way
that (for example) made 300,000 fragments of it, which happens very rarely.
(It was screwing up some other disk analysis tool which apparently decided
to allocate fixed memory blocks for stuff and not check they were big enough.)
The thing is, the files don't fragment if you don't write to them, and the
files that you want to read fast and sequentially are generally things like
programs or images or something like that, where you write them all in one
chunk to start with. Who cares if your mailbox file is fragmented? Plus,
Windows has had for a long time an API to preallocate files, so if you're
doing something like copying files, it doesn't get fragmented anyway.
One good way to get fragments is to compress a file. Since it's on-the-fly
compression, what happens is that you write a (I think) 64K segment of file,
and when you move away from it, it gets compressed down to however many 4K
segments it'll fit into, then rewritten (either in the same place or
elsewhere). So if you compress a big file after the fact, you'll find it
has bunches of fragments. They're all right near each other, but they're
fragments because there's gaps in between someone else can now use.
One of the things Windows does interesting is that it'll rearrange *where*
on the disk files are as it defrags, based on usage (and based on the defrag
tool you use, of course). So it's not just "defragging files", but "putting
an EXE close to its DLLs" and "putting programs you run at login all close
together" and stuff like that.
--
Darren New, San Diego CA, USA (PST)
Why is there a chainsaw in DOOM?
There aren't any trees on Mars.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |