Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

At the risk of proving your point (this part of the code is indeed a bit of a hash), but in the hope that this will help a little with learning, here are some answers:

1. The first do in your snippet does nothing - it's redundant. In the actual code you linked, though, it sequences the `get "/" ...` and the `get "/:short" ...` expressions into a single application initializer. When the app starts up (i.e. when `app` is called), this outer "do" runs through your endpoint-defining expressions and registers each endpoint in turn with the HTTP server.

2. That `get` function takes two arguments: the URI pattern and the action to run if the pattern matches. The whole rest of your snippet _is_ the second argument! Because of the low precedence of the "$" operator, using "$" means you don't have to enclose all that code in parentheses. It is a tiny bit of syntactic sugar that is wildly popular in Haskell-land because Heaven forfend any of your code ends up looking like LISP. ;-)

3. The answer is in the monad being used in this case to sequence these steps together (`ActionT Text IO <some return type>`). Think of `param "uri"` not as an expression returning a string, but a partially-constructed function that takes an HTTP request as an additional argument. The monad takes care of threading the request into this function when the request is actually handled, and `uri` will be bound to the resulting value.

4. I'm guessing it doesn't. Many type signatures in Haskell are optional, and are added if either 1) there's a genuine ambiguity in the code that needs to be clarified, 2) the author thinks it will make things clearer, or 3) the author hit a bug where the compiler inferred some crazy generic type that the author didn't intend or understand, and they put in some type signatures as sanity checks and constraints on what type is actually expected.



Thanks for your explanations! 2&4 make a lot of sense. 1, and even more so 3, lead to more questions than they answer, in my opinion. Monads appear to be an absolutely indispensible aspect of most substantial Haskell programs, but to me, they just look incomprehensible. I understand the advantages of a pure programming model for formal reasoning about programs, but in terms of communicating an intent with a program, I can't help thinking that the cure offered by Monads is far worse than the disease of mutable state.


The advantage of monads is that they whisk away a bunch of boring, repetitive boilerplate code that nobody wants to write and that people will even go so far in other languages as to create a bunch of global/thread-local/hidden-context variables to avoid writing!

The downside is that the abstraction and its applications, maybe a bit like pointers, do take a while to really master. Particularly when you start composing monad types to make other monads, as Scotty does with IO.




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

Search: