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

Nice question!

It "easy". Cause it takes less characters in your code: you don't need "type classes" of any form, you don't care about liftings etc. You can start from 2-3 lines of code and see immediate result.

But it's really not that "simple", cause without constant thinking about type of each expr it becomes very hard to trace long chains of monad operations very quickly. Plus types are great for verifying that you didn't break anything inside your "do" block (which is painful in dynamic env).


"Cause it takes less characters in your code: you don't need "type classes" of any form, you don't care about liftings etc. You can start from 2-3 lines of code and see immediate result."

Considering you linked directly to the roughly-equivalent Haskell, which contains neither of those things, that's a strange statement.

You will still need to care about liftings if you do monad transformers in a dynamic language, and if you implement your own monadic value in Clojure you may not literally type in an "instance" but you're still going to have to implement it.

You may have attained parity with Haskell's ease-of-parsing, but you certainly haven't shown it to be "easier". That is saying something, though... few languages can implement a monadic parser without horrid syntax. (Assuming you actually have... it's a common problem to think one has implemented something monadic without actually having done so. [1] But that's just a general comment, I'm not familiar enough with Clojure to have an opinion.)

However...

"Plus types are great for verifying that you didn't break anything inside your "do" block (which is painful in dynamic env)."

Emphasis mine. This tends to suggest that it is still not easier in a dynamic environment. Again, getting to even "almost as easy" is still a big win, though.

Interestingly, I'd suggest that the biggest problem with monads in a dynamic language is that when you do screw up, it's going to be harder for the human to understand it, and in the process, it's going to be harder for the human to come to understand monadic patterns in general. If someone is already very fluent in monadic patterns from Haskell experience, the craziness that might come out of a mistyped (in either sense) dynamic expression will probably be something they can handle in stride, but my guess is that it will be substantially more difficult to obtain that fluency in a dynamic language. In my personal experience, the fact that dynamic languages allow for more sloppiness comes out in code in a very real and profound way.

(And by "personal experience", I mean that while it is beyond the scope of this text box to elaborate further I've noticed that my own work in API creation between static and dynamic languages has noticeable differences in correctness and clarity-of-thought when I'm working in static and dynamic languages. I encountered another example just this last week of a confusion I'd made in an API of mine between two different entities that the dynamic type system had allowed me to conflate into one that a static type system would never have let me get away with. And I'm not even talking about Haskell's level of static typing... even conventional manifest typing would have prevented this mental error.)

[1]: http://www.jerf.org/iri/post/2928


To answer the question when STM is hard to use, you can imaging any case of simulation. Few years ago I worked with engine for real-time brokers trading simulations: thousands of independent players accept different information streams and make deals. Each deal is several steps of negotiations with two-phase commit. Plus different monitoring tools, timers, generators and randomizers.. Whole system was written in Erlang, and you know... two-phase commit is really hard to implement in right way without potential deadlocks and other problems. But it's looks good and "natural" (as to say) in Actors language. I used to try to do something like this with STM and I quickly gave up with mess of unreadable code.


This example was given to describe map/reduce pattern, not advice to use it instead of sum:

    reduce(operator.add, map(len, ss))
You know, it's hard to understand new concept. And it's twice harder to explain new concept with sophisticated code examples. So I used as simple code and situations as possible. The same for square_sum - it's easier "to see" functional pattern in map(f,l) than in (f(x) for x in l).

Regarding to debug function and partial function application, - it depends. As for me

    debug = partial(log, "debug")
is easier and meaningfully describe what's actually going on. But here we have only one function, what if you have to create 5-6 same functions? Would you prefer "def" syntax instead of partial? I have one more example of using this pattern in more sophisticated situation - code listing for dictionary binding to list of functions, "partial" looks really naturally.


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

Search: