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

> What the heck is "m t"?

It's worse than that! What the heck is "->"?

But I don't particularly buy the argument. Alright, here I go:

    def main():
      x = input
      y = input
      print(x + y)
Uh oh...

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unsupported operand type(s) for +: 'builtin_function_or_method' and 'builtin_function_or_method'
What the heck is "Traceback", "<stdin>", "<module>", "TypeError", "operand", "builtin_function_or_method"? Did I have to understand all those to write the simple Python program?

The claim that you have to understand everything about a failure case in order to write simple programs doesn't seem valid to me. It doesn't resonate with how I've learned languages before. However, I may not have the best perspective because I'm very familiar with both Python and Haskell so I don't have the "beginners mind" any more. I would be interested to hear from someone who's a beginner (perhaps in both languages) whether they think the Haskell program requires more understanding than the Python one https://news.ycombinator.com/item?id=37402253



My point isn't that it errors. It's completely reasonable to expect even a beginner to do basic troubleshooting. My point is that the error specifically mentions monads. So will the documentation for `do` and `<-`. Anybody looking to use `IO` beyond a copy-and-paste level will be thrust headfirst into monad-land. This doesn't mean `IO` cannot be used at all without understanding monads, just that it's extremely explicit that something unique and interesting is happening when you do. In fact, I expect most people build their intuitions around monads by playing around with `do` notation.

This isn't the case in Python where input and output are standard functions. The syntax for function declaration and variable assignment just work.

If our requirements changed to now read and sum an arbitrary number of inputs together, I'd expect a beginner could change the Python program to do so. I'm skeptical they could make the required changes to the Haskell version (without understanding monads).


> My point isn't that it errors. It's completely reasonable to expect even a beginner to do basic troubleshooting. My point is that the error specifically mentions monads.

Right, and the Python errors mention all sorts of things a beginner is not expected to understand, like "builtin_function_or_method". I don't think "understanding builtin_function_or_method" is required to write the Python and I don't think "understanding Monad" is required to write the Haskell.

> If our requirements changed to now read and sum an arbitrary number of inputs together, I'd expect a beginner could change the Python program to do so. I'm skeptical they could make the required changes to the Haskell version (without understanding monads).

Where do I have to "understand monads" to write this?

    main = do
      iters <- readLn
    
      let loop n total =
            if n == iters
            then print total
            else do
              x <- readLn
              loop (n + 1) (total + x)
    
      loop 0 0
I had to understand that in Haskell looping is done via recursion (which is mindbending initially, if you come from imperative programming), but I don't see that I had to understand monads. FWIW the Python that I'd write is

    def main():
        iters = input()
    
        total = 0
    
        for _ in range(iters):
            x = input()
            total += x
    
        print total
This is simpler. But I could write a Haskell version that uses an IORef to get roughly the same code structure as the Python.

    main2 = do
      iters <- readLn
    
      total <- newIORef 0
    
      for_ [1..iters] $ \_ -> do
        x <- readLn
        modifyIORef' total (+ x)
    
      theTotal <- readIORef total
    
      print theTotal
I would say this requires understanding the mutability/immutability distinction to know why we use an IORef at all (but you'd get that with OCaml[1] too) and it still requires understanding do notation, but I don't see that it requires "understanding monads"!

Now, if I were writing this for real I probably would use a version with a state monad transformer so it was

    main3 = do
      iters <- readLn
    
      total <-
        flip runStateT 0 $ for_ [1..iters] $ \_ -> do
          x <- lift readLn
          modify' (+ x)
    
      print total
That would require some understanding of monads so that you can understand how they are transformed with monad transformers!

[1] https://www.cs.cornell.edu/courses/cs3110/2018sp/l/14-mutabl...




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

Search: