Hacker Newsnew | past | comments | ask | show | jobs | submit | dfeltey's commentslogin

Not really my project, but racket, specifically DrRacket has a handful of easter eggs for various holidays and the birthdays of core developers.


What the hell did I just watch?


I do understand your point, but purity is one of the defining characteristics of Haskell, and one of the features that differentiates it from most other languages, so I think it should be mentioned up front when introducing Haskell.


Mention it, maybe, but pointing out how great it is not to have to deal with that messy "real world" is bad marketing. It makes you think "oh, so all these benefits only exist in the magical fairy land and not in the real world where I work?"


I understand what you're saying. It would be better to just talk about the enforced separation between pure code and code with side-effects, and explain that it's possible to structure a normal program so that it's mostly pure.


You are just making a claim though, no one know if it is actually true. Semantic purity doesn't necessarily lead to human clarity, which is one of the mountains Haskell has had to climb: it doesn't seem "easier" or "more simple" than other approaches, only claims of safety might hold up to some scrutiny.


You will note that I make no claims about clarity, only that it is possible to separate pure from impure code in Haskell (which is certainly true).

The problem with Haskell and clarity are, in my experience, twofold:

- large amount of high-level concepts to absorb (though not everything is necessary to start producing code)

- the power of the language is its own worst enemy at times - it is possible to write a pipeline of complex computation with very little work, which leads to less code but less readability (on the other hand, Haskell functions are typically short, which helps a lot with maintaining up-to-date comments)

On the other hand, the separation between pure and impure code is not a complex notion per se, and reasoning about pure code is made much easier.


Right. It is quite easy to build convoluted Haskell code just as it is easy to to build convoluted Java code.

One of my primary complaints about Haskell, however, is that Haskell code is impossible to debug. You can reason about it, the type checkers can check deep properties about it, but it is difficult to actually observe the computer executing it! To me, this is a deal breaker.


> Right. It is quite easy to build convoluted Haskell code just as it is easy to to build convoluted Java code.

I don't think it's quite as easy, but I'll concede the point so I can make the more important point: it is much easier to write clear Haskell code than clear Java code (at least, "clear" as I understand clarity, YMMV).

> You can reason about it, the type checkers can check deep properties about it, but it is difficult to actually observe the computer executing it!

Certainly purity makes it hard to observe, and laziness makes it hard to understand how the program executes. However purity also means that static debugging (e.g. QuickCheck) is far more powerful than in other languages so dynamic debugging (actually watching your running program) is less needed. In fact I do far less debugging in Haskell than in Python, say. I first fight the compiler. When I win, the end result is correct more often in Haskell than in any other language I've ever used.

> To me, this is a deal breaker.

That's fair enough. Everyone has their own preferences. Personally I've never noticed it be a problem.

Disclaimer: I don't write performance sensitive code. I expect performance tuning in Haskell is harder than what I've described above.


> I first fight the compiler. When I win, the end result is correct more often in Haskell than in any other language I've ever used.

And now we get to a few of questions related to bias:

* Given that debugging is difficult in Haskell, do Haskell programmers to get in the habit of statically debugging their code? Is that really more "better" than dynamic debugging? Some type error messages in languages like Scala and Haskell can make static debugging quite painful.

* Does Haskell's powerful type system bias it to well understood problems with meaningful types? I attended a WGFP meeting once, and it was amazing to hear people like SPJ talk about how they found elegant solutions to icky programming problems, but I thought that, given a dirtier language, you could just write a dirty solution and be done with it.

* Would Python's dynamic type system make it more suited to problems with dirtier less clear types when compared to Haskell? If you know both Haskell and Python, do you divide your potential programs into "Python programs" and "Haskell programs"?

* When one writes Haskell code, do they really not have to debug and test their code?


> * Given that debugging is difficult in Haskell, do Haskell programmers to get in the habit of statically debugging their code? Is that really more "better" than dynamic debugging? Some type error messages in languages like Scala and Haskell can make static debugging quite painful.

I'm not sure what you mean by "static debugging". You're going to get type error messages while you're trying to compile, but certainly not at runtime. GHC really does its best to make them as explicit as possible and often suggests the correct fix.

> * Does Haskell's powerful type system bias it to well understood problems with meaningful types? I attended a WGFP meeting once, and it was amazing to hear people like SPJ talk about how they found elegant solutions to icky programming problems, but I thought that, given a dirtier language, you could just write a dirty solution and be done with it.

Not really. It is really a general purpose language, and you find very good libraries to interact with less strongly typed systems (eg, JSON).

> * Would Python's dynamic type system make it more suited to problems with dirtier less clear types when compared to Haskell? If you know both Haskell and Python, do you divide your potential programs into "Python programs" and "Haskell programs"?

If anything it would be more a question of libraries. One thing you won't be able to get in Haskell though is something like an ORM, with lazy-loaded collections and stuff like that. I find myself missing SQLAlchemy. Persistent does not have the same flexibility, despite Esqueleto which looks nice.

> * When one writes Haskell code, do they really not have to debug and test their code?

No. The best type system does not help when you write the wrong values with the right type in your program, or get the logic of your program wrong. But the errors tend to be more interesting. Also, you have a very powerful system to test the pure parts of your code (QuickCheck).


I don't have good answers to your first two questions, since they're very open ended. I can give you my personal experience regarding the second two.

* Would Python's dynamic type system make it more suited to problems with dirtier less clear types when compared to Haskell? If you know both Haskell and Python, do you divide your potential programs into "Python programs" and "Haskell programs"?

No, I classify my potential programs into "Haskell programs". I haven't missed Python once.

* When one writes Haskell code, do they really not have to debug and test their code?

Haskell programmers still have to debug and test, but I find it somewhat easier than I've found it in other languages.


You're overstating it. Debugging Haskell code is definitely harder than in other languages.

But it's far from impossible (I use Debug.Trace successfully), and you do it far less often.

So debugging takes 5 times more effort but needs to be done 15 times less than in other languages.

At least that's the deal I'm getting and I don't usually find myself debugging much so it's not a grave concern.

I'd say lack of non nullability or pattern matching are worse show stoppers.


Have you looked into Debug.trace? The type of trace is "String -> a -> a". This is a 'pure' function that 'ignores' the first argument and returns the second unmodified. What actually happens is that the first argument is a String that gets printed to stdout. Furthermore, once you give it the first argument, it is simply the identity function, which allows you to easily place it anywhere in you code.

For example, if you have a function: add x y = x+y, and you wanted to see all of the inputs add gets, you could do: add x y = trace (show (x,y)) $ x+y.

For anyone confused about how such a function is possible in Haskell, not that it is in Debug, and the documentation clearly states that it should only be used for debugging.

EDIT: You could also do traceShow (x,y) $ x+y.


I've seen this, it basically allows us to generate execution trace trees, which is quite trivial in most languages must somehow hard in Haskell.

I've studied a lot of mechanisms for debugging Haskell code, and some of the debugging mechanisms taken for granted in other languages can be clawed back. But at the end of the day, it is a struggle: the purity (or more accurately, laziness) that is supposed to help so much ends up hurting in at least one aspect.

Perhaps why Haskell programs are so easy to reason about statically is because they are so hard to reason about dynamically :)


Your last point is the other way around:

Haskell has excellent static reasoning/debugging facilities therefore there is little pressure to make good debugging tools.

I believe purity should make debugging easier, not harder. Laziness should only make performance debugging harder, not correctness debugging.

There is much room for improvement in this space.


As a day-to-day Haskell programmer I'm happy to say that purity makes it easier to understand the programs that I write. Still, you're welcome to suggest that's an entirely subjective anecdote if you like.


You'd think that an empirical experiment with new programmers could prove the point, or at least provide conclusive evidence.


Personally I wouldn't think that. I think that such things are far too complicated to be amenable to scientific study.


I would normally agree, but specific usability claims are being made continuously about the benefits of purity, while many programmers think of Haskell has being anything but.


It doesn't say you don't have to deal with 'that messy "real world"'! It is called Real World Haskell after all.


I think it is great "truth in marketing", because going beyond purity requires talking about things like monads, and then they've lost most of their audience anyways.

It is better to lose those not interested in purity early rather than have those uninterested folks become disappointed later.


I don't know why anyone would use the Integral typeclass over just Int or Integer in a simple program like this, but you wouldn't need Num in addition to Integral, every instance of Integral must also be an instance of Real, and instances of Real must be instances of Num.


I'm not sure whether you would consider this paper systems-oriented, but it's fun and sort of practical. "A Play on Regular Expressions" is literally a 3 act play about efficiently implementing regular expressions with code in Haskell. I've been working through it and trying to adapt some of the code for a workshop I'm giving this summer, and it's been very readable and interesting.

http://sebfisch.github.io/haskell-regexp/regexp-play.pdf


Thanks! I'll try it out once I can understand Haskell syntax..


I used to use GrubHub all the time when I lived in Chicago and always had a good experience with them. Since I've moved there aren't very many restaurants using these types of services where I live now, but I would definitely use a similar service if it had decent adoption locally.


I graduated from the University of Chicago, and they have a handful of undergrad classes using functional languages. The intro comp sci courses were using Haskell for the honors class, and Racket for the non-honors version when I took it. The compilers course there is taught using ML, though the fact that UChicago has several faculty who work on the development and maintenance of Standard ML may have something to do with this.


This is sort of interesting because the Math department at UChicago has had undergraduate TAs for a long time for at least the first year courses, and I believe a couple of the second year courses, but it seems only recently has the CS department done the same for its first year courses.


I teach RobotC to a FIRST robotics team, I really dislike it sometimes. The IDE is pretty bad, and only runs on Windows, and up until recently all variables in a RobotC program would implicitly be global. They fixed that with 3.5, and are aiming towards a more ANSI-C compliant implementation, but I still find it a pretty frustrating platform sometimes.

http://www.robotc.net/blog/2012/10/24/robotc-3-5-global-vs-l...


This was my one complaint as well, and it happens with the example given of any'

Defining any' as

any' f xs = foldl (\acc x -> f x || acc) False xs

Then trying to evaluate any' even [1..] runs forever, but if we modify it slightly to use foldr instead as

any' f xs = foldr (\x acc -> f x || acc) False xs

Then evaluating any' even [1..] terminates basically immediately with True.


Thanks much for the feedback. I clearly didn't understand them as well as I thought I did, though after reading http://stackoverflow.com/a/3085516/337184 I think I understand a bit more.

I'll update the post with a correction, and eventually write a "how I learned to stop worrying and love the difference between foldl and foldr" post. :-)


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: