Hacker News new | ask | show | jobs
by jrockway 5860 days ago
Most important, though, is the case of the first and most common error. Here, the language will very explicitly require you to handle the case that "Nothing" will potentially be returned.

Well, actually no. Consider:

    divide :: Int -> Int -> Maybe Int
    divide x 0 = Nothing
    divide x y = Just $ x / y

    printResult :: Maybe Int -> IO ()
    printResult (Just x) = print x
Now, run:

    main = do
      putStr "Type a number: "
      x <- readLn
      divide 42 x >>= printResult
This will still die if you type 0, because there is no pattern to match the Nothing case. Sure, you can run Catch to see that you made a mistake, but the compiler doesn't care. (At least you can run Catch to determine that you messed up, though. If you are using Java or Ruby or something, you are just hosed.)

Anyway, my usual error is not null or using the wrong variable or typoing something. It's usually failing type checks because I forgot a coercion, or just plain wrong code. Exceptions prevent null returns, and I am lucky with respect to the other two.

2 comments

It needs to be fixed up a bit. You can somewhat resolve this issue by compiling with -Wall, at which point it will warn you that your pattern matching is non-exhaustive.

    import System.IO

    divide :: Int -> Int -> Maybe Int
    divide x 0 = Nothing
    divide x y = Just $ x `div` y

    printResult :: Maybe Int -> IO ()
    printResult (Just x) = print x

    main = do
        putStr "Type a number: "
        hFlush stdout
        x <- readLn
        printResult $ divide 42 x
Interesting. I assumed Haskell would at least warn you. But it's probably only a matter of time before Catch is built in to the compiler, at least as an option.
OCaml does warn you:

    : kragen@inexorable:~/mail ; ocaml
            Objective Caml version 3.10.2

    # let divide x = function 0 -> None | y -> Some (x / y) ;;
    val divide : int -> int -> int option = <fun>
    # let printResult = function Some x -> print_int x ;;  
    Warning P: this pattern-matching is not exhaustive.
    Here is an example of a value that is not matched:
    None
    val printResult : int option -> unit = <fun>
    # printResult (divide 9 3) ;;
    3- : unit = ()
    # printResult (divide 10 0) ;;
    Exception: Match_failure ("", 1, 18).
    #