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

Ok let me tell you the criteria. There are two.

First: The monad allows for composition of functions. Returning two values does not. It breaks the flow of a function pipeline and forces you to handle every error in the same way.

Second: Extracting the value via pattern matching guarantees that the error will either be handled or used correctly. This is a way to 100% guarantee that there are No runtime errors. That's right. Using the error monad with pattern matching makes it so that there is zero room for runtime errors.

Why create a language that has runtime errors? Create a language that forces you to handle all possible runtime errors before it even compiles.

According the criteria of safety, zero runtime errors, and expressivity via composition the monad is the Best solution. There is literally no other way of error handling that I know of that can catch runtime errors at compile time.

I know you tried to flip my statement on it's head by using the term "criteria" as if there are many many different criteria for "best." And you are right, programming is an opinionated thing. However, ZERO runtime errors is a too powerful of a feature to assign to a specific criteria. Such a feature is so powerful, it should be part of EVERY criteria.

If you don't understand completely what I mean by "composition" or how pattern matching and a maybe monad can guarantee a runtime error will NEVER occur, ask me to elucidate, I'm happy to clarify.



I'm interested in the zero runtime errors piece - how would a language with the maybe monad handle an out-of-memory error at runtime?


There is a way of which (to my knowledge) is not implemented in any technology.

Presuming you know how the maybe monad (or similar named monads) handles errors. A MaybeOutOfMemoryError works in a similar way in the sense that any attempt to use the value meaningfully will force you to handle the error.

   data MaybeOutOfMemoryError a = OutOfMemoryError | Some a 

   ioFunction :: MaybeOutOfMemoryError a -> IO

   ioFunction OutOfMemoryError = println "ERROR"
   ioFunction Some _ = println "No ERROR"
exhaustive pattern matching with the error flag enabled makes it so that if you forget the OutOfMemoryError case an error will occur during compile time.

Any function that can potentially trigger a memory error should be forced to be typed like this. However in programming, ALL functions can potentially do this, and side effects outside of the scope of the function (total memory available) will trigger it meaning that the only way to do this effectively is to make ALL functions typed this way. Which is inconvenient to say the least.

That being said you can just type the main function as something that can only accept this monadic value forcing users to wrap this handling in a top level function:

   myWrittenProgram :: MaybeOutOfMemoryError a
    -- not defined in this example

    -- main is forced to be typed this way just like how in haskell it is forced to be typed IO ()
   main :: MaybeOutOfMemoryError a -> IO ()
   main Some a = printLn a
   main OutOfMemoryError = printLn "Error out of memory"
Obviously the above has some issues with the rest of haskell syntax and the way things are done, but I'm just showing you a way where it is possible to make sure that a memory runtime error does not happen (that is an unhandled runtime error).

That being said unless you know haskell or know what a maybe monad is, you wouldn't be able to fully comprehend what I said. Exception monads exist in haskell, but nothing is forcing the main function to be typed this way.




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

Search: