No Runtime Exceptions - Still not computing

330 views
Skip to first unread message

Dave Ford

unread,
Oct 6, 2016, 10:13:32 PM10/6/16
to Elm Discuss
I have listened to a number of podcasts where Richard Feldman boasts about never getting a runtime exception. 

I am having a hard time grasping the concept. I think I look at runtime exceptions a bit differently. I look at them as a positive. A programmers tool. A debugging tool. A way to communicate up the call stack. A way to separate the error stream from the standard stream.

For example, a java newbie might do this:

void myFunction(int x){
   if(x < 1){
      log("error: x must be >= 1"); 
      return 0
   }      
   return x * x * x;
}

A more experienced developer might do this:

void myFunction(int x){
   if(x < 1){
      throw new IllegalArgumentException("error: x must be >= 1"); 
   }      
   return x * x * x;
}

I look at runtime exceptions as a good thing. It's kind of like having two returns. One return for the normal answer (return). And another for error conditions (throw). Just like unix has two output streams: one for normal messages and one for error messages. This allows the caller to handle the normal return value and the top-level caller to handle (i.e. catch) the errors (usually by logging a stack trace). 

So I don't get it. If I don't have runtime exceptions, what do I do when someone passes an invalid argument? What do I do if some pre-condition is not as I expected? Some JSON returned from the server is not in the correct format? Are we back to just one return value for both error conditions and normal conditions?

Technically speaking, in java, if I wanted to create an app with no runtime exceptions it would be real easy. I could just swallow invalid arguments and let the program fail in a super mysterious way, farther upstream (the opposite of fail-fast). But I wouldn't boast about that. Or I could just have a try/catch in my main method that caught every exception and swallowed it or logged it.

If Richard said he wrote apps with no bugs. That would be impressive. But an app with no runtime exceptions seems like a silly thing to boast about. I see 3 kinds of bugs in my java apps:

1. Compile errors. These are the easiest to deal with. These are preferred. But I don't see the compiler catching the above mentioned IllegalArgumentExceptionOr a piece of bad JSON from the server.

2. Runtime Exception. Like a NullPointerException or an IllegalArgumentException. I love these kind of bugs. Super easy to find. Super easy to fix. A stack trace tells me exactly where to look. These kind of exceptions have never been a thorn in my spine. 

3. The mystery bug. Program is just not producing the correct output. No idea why. No idea where to start looking. No error message. No stack trace. These are the worst kind of errors.

In my opinion one of the key differences between an experienced developer and a beginner developer is that an experienced developer fails-fast with compile errors (#1) or runtime exceptions (#2). Beginner developers fail mysteriously with (#3).

So, based on my understanding, the whole "no runtime exceptions" concept is just not computing.

But I am new to Elm. Surely I am misunderstanding something. Please tell me what I am missing.


Joey Eremondi

unread,
Oct 6, 2016, 10:19:13 PM10/6/16
to elm-d...@googlegroups.com
What actually happens is "no uncaught runtime exceptions".

If an operation can fail, it *MUST* be expressed in the type, and when you call the operation, you *MUST* handle the failure case.

Your program will never crash because of a null pointer or file-not-found or an array out of bounds, but it also will not fail silently unless you go out of your way to make it do so. What will happen is you will handle the error case, and either come up with a sensible default, or tell your program to display some error message, or do something else to properly handle the error.

It means that there's no forgetting to check the error codes, like you get in C all the time. And there most certainly will not be an "undefined is not a function" nested deep in some complex operation chain, as you get all the time with JS.

Take a look at Array.get: http://package.elm-lang.org/packages/elm-lang/core/latest/Array#get

If you have an array of T, instead of returning a T with the possibility of a crash, it returns a Maybe T. The programmer is forced to check if there was an array-out-of-bounds error. The program will not compile otherwise.

(That said, in the common case, like iterating through a whole array, there's Array.map, which never fails, because it only looks at array elements that are actually there).

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Dave Ford

unread,
Oct 6, 2016, 10:48:26 PM10/6/16
to elm-d...@googlegroups.com
Thanks Joey. 
 
you will handle the error case, and either come up with a sensible default, or tell your program to display some error message, or do something else to properly handle the error.
You mean, do exactly like I showed in the java newbie example? What would be considered an anti-pattern in java? How is this a good thing? It seems like a step backwards.

Often there is no way to "handle" the error. There is no sensible default. It's a programmer error and throwing an exception is the most logical thing to do. 

Unless I am missing some key concept, this will make your programs less reliable. True, there will be no runtime exception. But there will be bugs. And more noise.

Again, I will admit that I am new to Elm. And may be missing something. I totally get the whole "maybe" thing. And I see the advantage of that. 

But, if I am not mistaken, we are back to C in the sense of "no throw"? C#, Java, JavaScript, and Scala have the keyword throw. VisualBasic, Python, Ruby, F# and Clojure have raise

Is there no throw/raise in Elm? We must use "return" for both standard return and error return. Is that correct?

I'm not trying to be a troll. There are lots of things I love about Elm. I'm just trying to understand the language. Thanks.


Duane Johnson

unread,
Oct 6, 2016, 11:07:40 PM10/6/16
to elm-d...@googlegroups.com

On Thu, Oct 6, 2016 at 8:13 PM, Dave Ford <df...@smart-soft.com> wrote:
2. Runtime Exception. Like a NullPointerException or an IllegalArgumentException. I love these kind of bugs. Super easy to find. Super easy to fix. A stack trace tells me exactly where to look. These kind of exceptions have never been a thorn in my spine.

I'm genuinely surprised by your experience / reaction to runtime exceptions. My experience has been the exact opposite. Runtime exceptions can only be found through tedious exercise of every branch of code through all possible states, which creates a horrible burden on the developer who wishes to not have to worry about how old code might break as new code is added and the size of the project (and possible states) increases.

When you say you love these kind of bugs, are you saying you like to go through your program and try this or that input and see if you can get it to throw an exception? What if you change the code somewhere else, but in a section of code that *might* affect other parts of your codebase--do you then go back to each of the other parts of your program and try to think of new ways that exceptions might have be able to be raised?

I wrote part of a large (very large--possibly the largest open source Ruby app, called Canvas) and at some point, the complexity becomes mindboggling. It slows down project development when you can't check (at compile-time) whether a change here affects the code *there* (and *there*, and *there*, and, does it affect *this* code?) The motivation of Elm, as I see it, is to push as many classes of errors as possible into the compile-time error space. Not all can be pushed into that domain, but many can--and that's considered an advantage because as project size increases, you can still move with confidence.

Possibly related--I found it instructive to listen to Richard's "Making Impossible States Impossible" presentation at ElmConf.

Dave Ford

unread,
Oct 6, 2016, 11:33:43 PM10/6/16
to elm-d...@googlegroups.com

Duane. Don't get me wrong. I prefer compile errors over runtime errors.  And if Elm can catch more errors at compile time without adding a bunch of noise to my code that is a good thing obviously.

But runtime errors are unavoidable.  It's not possible for the compiler to catch every possible error condition. The question is,  does the language have an elegant mechanism to deal with runtime exceptions? Especially in a separate flow from the normal return value.

And from what I am hearing the answer is either no or no one is telling me what it is. 

So my question is: does Elm have something similar to throw/raise?


--
You received this message because you are subscribed to a topic in the Google Groups "Elm Discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elm-discuss/00CgYDiMvBI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elm-discuss+unsubscribe@googlegroups.com.

Ambrose Laing

unread,
Oct 6, 2016, 11:43:56 PM10/6/16
to Elm Discuss
Elm has datatypes called Maybe, Result and Task.  You mentioned Maybe already, which may be understood to mean a list of at most one item, or a data type with either missing data, or an unspecified error.  Result allows you to specify the error and propagate it, so take a look at that.  Then look at Task also.

To unsubscribe from this group and all its topics, send an email to elm-discuss...@googlegroups.com.

Max Goldstein

unread,
Oct 7, 2016, 12:00:30 AM10/7/16
to Elm Discuss
Yes, Result is worth looking at. It's like Maybe, except the error case can carry some information too (usually a string). Task is used for asynchronous effects (e.g. HTTP requests) which often can fail in odd ways. I'd focus on Result for now, as all the tooling I'm about to mention is the same across these types.

Joey mentioned we like to map over arrays. Well, you can also map over a Maybe or a Result. The trick is that these are also data structures; they just happen to hold at most one (successful) element. So you find yourself doing things like

String.parseInt "not an integer"
|> Result.map doSomethingWithTheInt
|> Result.andThen doSomethingWithTheIntThatCouldFail

This way you build up pipelines that ignore the fact that you don't actually have an integer. The error short-circuits the pipeline and gets handled at the end, so it's like throwing in that you can handle the error at a distance. And you can collapse many errors into one case that you handle all in one place. (minor detail: this is using the argument order for andThen coming in 0.18)

I few weeks ago I had to add a lot of try...catch blocks around someone else's code, and let me tell you, it wasn't fun.

Peter Damoc

unread,
Oct 7, 2016, 3:32:30 AM10/7/16
to Elm Discuss
On Fri, Oct 7, 2016 at 5:13 AM, Dave Ford <df...@smart-soft.com> wrote:
So, based on my understanding, the whole "no runtime exceptions" concept is just not computing.

But I am new to Elm. Surely I am misunderstanding something. Please tell me what I am missing.

Programs will always have code that could rise "exceptions" or errors. 
A runtime exception is a kind of exception that bubbled up to the surface and causes the application to either crash or end up in an unstable state. 
No one wants these kind of exceptions.

No, back to you example. 
It is very useful that you said that  "It's kind of like having two returns" because that is a GoodThing™!
Elm makes this explicit. 
In Elm, in those cases, you return a type that can have 2 kinds of values: a success value and a failure value. 
You can either return a Maybe (a simpler type where on failure you just say that it failed) OR you can return Result (a more sophisticated type where failure has its own informative type). 

You will have to handle ALL these failure values, even if it is just to silence them by unpacking the Result or Maybe using a default value (Result.withDefault and Maybe.withDefault). 
This means that there is no exception that will bubble up unhandled at runtime and crash your app.



--
There is NO FATE, we are the creators.
blog: http://damoc.ro/

John Orford

unread,
Oct 7, 2016, 4:06:55 AM10/7/16
to Elm Discuss
+1 Peter

Elm forces you to explicitly handle failures - whereas you in many other languages the use of exception handling is optional.

this freaks some people out, because it's so deeply baked in, that they can miss it's there at all : )

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.

Joel McCracken

unread,
Oct 7, 2016, 10:06:49 AM10/7/16
to Elm Discuss
I think your suspicions are largely right, and your concerns are valid. However:

Not all exceptional situations are created equal. Some happen more frequently than others, and many are due to programming errors, where things just aren't "wired up correctly", and not all cases are handled. Elm's type system helps with these.

I do not believe you can use the type system to prevent stack a overflow, for example. At least, you can't do it in a  "general way", e.g. static analysis can catch the stack overflow conditions before they occur.

There are lots of ways though that you may encode the "restraints" of your system. In your example, I would say that your function should not take an "Int", instead it should take a "Nat". Then, you have a function "intToNat" that returns a "Result" -- either it successfully converted the "Int" to a "Nat", or it failed, with an "Error" (e.g. the int was <1). You use this function as far out toward the "edge" of your system (ideally, directly in the update loop function). The update function is the right place to deal with invalid inputs, as you may choose to tell the user about the problem, or log an error with something like Bugsnag, etc.

Garbage in, garbage out, of course. But, the tools elm gives you allows you to have simpler "core" logic. And you may be sure that this core logic is free of certain classes of errors.

Dave Ford

unread,
Oct 7, 2016, 1:08:16 PM10/7/16
to elm-d...@googlegroups.com
This means that there is no exception that will bubble up unhandled at runtime and crash your app.

Peter, I think you may be misunderstanding the intent of exception bubbling. The idea is not to have the exception bubble up to the top and crash your app. The idea is this. Suppose you have function1 call function2 and function2 call function3 and function3 call function4. And suppose function4 throws an exception. An unrecoverable exception. And suppose that the sole purpose of the exception is to indicate a programming error or a system problem. There is nothing to be "handled". No possible "recovery". The only reasonable way to handle the exception is with a "generic exception handler":
  1. log a message
  2. print a stack trace
  3. update the ui with a generic "system error: please see log" message.
For this situation, the established best practice (as far as I know) has always been to allow that exception to bubble up to main and have one top-level "generic exception handler" in main. 

Runtime exceptions are inevitable. An awesome compiler can certainly move certain categories of exceptions from runtime to compile time. Form what I am hearing, Elm is pretty good at that.

But exception bubbling is a feature. An extremely useful feature. Language level support for exceptions has been a staple of every programming language since C. I do not consider Maybe and Result to be a useful substitute for language level exception support. I could do Maybe and Result in C.

Even unix has separate streams for standard versus error. 

If every function in between main and function4 has to explicitly propagate the exception up the call stack, I see that as adding no value and a bunch of noise to the app. 



Joey Eremondi

unread,
Oct 7, 2016, 1:11:03 PM10/7/16
to elm-d...@googlegroups.com
If you want Exception Bubbling like that, use Maybe.andThen or Result.andThen. These are exactly what they are for.

You can bubble your exceptions as high as you like, but (1) that bubbling is always expressed in the type signature, and (2) there's always something that will catch it eventually, it can't bubble past the top and crash the program.

"No Runtime Crashes" might be a better slogan. We have runtime knowledge of failure, but we have to do something about it. It will never bring the whole program down.

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.

Joey Eremondi

unread,
Oct 7, 2016, 1:14:42 PM10/7/16
to elm-d...@googlegroups.com
Runtime exceptions are inevitable

The  successful applications written in Elm proves that they are not. You can keep saying it, but it doesn't make it true.

This is a path that Rust is following as well, so it's not like we're the only people in the tech community with this attitude.

I could do Maybe and Result in C.

Yes, but without higher order functions, you can't do Maybe.andThen and Result.andThen, or Maybe.withDefault, which is what makes them more useful than the C structures. And, you'd have no guarantee that a null pointer along the way wasn't going to bring down your whole program. Elm doesn't allow safety, it enforces safety.

Max Goldstein

unread,
Oct 7, 2016, 2:03:43 PM10/7/16
to Elm Discuss
Part of what makes runtime exceptions not inevitable is that many such errors come from I/O actions, which Elm handles with care. If you have a specific example of an inevitable runtime error, we'd like to hear it.

Theoretically of course, Elm doesn't solve the halting problem and you can always blow the stack or exhaust memory. So it's not terrible that any function can call Debug.crash, which is an uncatchable exception. It's useful for when you think something can never, ever, happen.

Peter Damoc

unread,
Oct 7, 2016, 2:10:45 PM10/7/16
to Elm Discuss
On Fri, Oct 7, 2016 at 8:08 PM, Dave Ford <df...@smart-soft.com> wrote:
But exception bubbling is a feature. An extremely useful feature. Language level support for exceptions has been a staple of every programming language since C. I do not consider Maybe and Result to be a useful substitute for language level exception support. I could do Maybe and Result in C.
 
In most languages, exceptions happen when you try to do something deep within a tree of function calls. This maybe has to to with the side-effect nature of how things are handled almost everywhere. So, for example, I could try to read a file in python and get some file missing exception. Then it would be helpful to have that trace. 

However, in Elm, things are different. Elm is both purely functional AND declarative. 
You can imagine Elm as being an imperative shell around a functional core. The Elm program is the functional core, the runtime is the imperative shell. All possible exceptions happen outside of this core. There is nothing really to bubble up. All the code that can blow up is in the shell. All the code that interacts with the code that can blow up, is very close to the shell (at the level where you would have the generic handler). Inside the Elm code, is predictable code. Like, you want the first element of a list? What if the list is empty? You need to handle that case! If you think that this will never happen, than maybe the list is not the data structure that models your scenario, maybe you need something like a non-empty list. If empty lists are possible and you have a default value for the cases when the list is empty, you use Maybe.withDefault defaultValue <| List.head someList.  

If you can come up with a practical scenario where you would have an exception, I or someone else around here could tell you what would happen in Elm in that context.

Finally, you do have the option of crashing the entire program with Debug.crash and you can have a top level handler around Elm that would do what you think it is best to do in these cases. 
Here is a minimal alteration of the buttons example to demo this (you can paste it in elm-lang.org/try )

import Html exposing (div, button, text)
import Html.App exposing (beginnerProgram)
import Html.Events exposing (onClick)


main =
  beginnerProgram { model = 0, view = view, update = update }


view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [ onClick Increment ] [ text "+" ]
    , div [][ button [ onClick Crash ] [text "Crash"]]
    ]


type Msg = Increment | Decrement | Crash 


update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1

    Crash -> 
      Debug.crash "BANG!" 

Kasey Speakman

unread,
Oct 7, 2016, 2:33:08 PM10/7/16
to Elm Discuss
Hi Dave.

Check out this link, but scroll down to the section titled "Should functions throw exceptions or return error structures?". It's F#, but the comparison is valid to exception handling vs "functional" error handling using Maybe (Option in F#) and Result.

In my back-end F# code, I no longer handle exceptions, generally speaking. I take functions which normally throw exceptions (like SQL queries) and wrap them in an Result type. Then using things like `map` and `bind` (aka `andThen`), I can continue my workflow only on success. Then at the edge of the application, I can deal with the errors differently based on which specific error occurred. Some could even invoke a program crash if that makes sense to do. But then I know exactly for which cases I am pushing the self-destruct button.

All that said, I think you are focusing on the trees and not the forest, because there's comparatively little need to do this kind of error handling in Elm, considering it only allows you to write pure functions. The main times you end up with Result types are parsing and comms. Maybe is more frequent, but more about presence than error handling.

Dave Ford

unread,
Oct 7, 2016, 3:48:35 PM10/7/16
to elm-d...@googlegroups.com
On Fri, Oct 7, 2016 at 10:14 AM, Joey Eremondi <joey.e...@gmail.com> wrote:
Runtime exceptions are inevitable
You can keep saying it, but it doesn't make it true.

Sorry. I was using the term "runtime exception" in the more general sense: exceptional conditions that occur at runtime (not caught by the compiler) like:
  • Invalid function args
  • Malformed JSON
  • Server down

Dave Ford

unread,
Oct 7, 2016, 4:02:28 PM10/7/16
to elm-d...@googlegroups.com
On Fri, Oct 7, 2016 at 11:10 AM, Peter Damoc <pda...@gmail.com> wrote:
If you can come up with a practical scenario where you would have an exception, I or someone else around here could tell you what would happen in Elm in that context.
Yes. The example I gave when I started the thread (sorry for the java syntax - i'm new):

function foo(int x) throws IllegalArgumentException{
  if(x > 10) throw new IllegalArgumentException("Bad x");
  return x * x * x;
}

Finally, you do have the option of crashing the entire program with Debug.crash 

This sounds pretty similar to throw.

I'll have to play around with Debug.crash and Result.andThen a bit before continuing my complaining. 

Thank you everyone for your patience and thoughtful responses.

Dave Ford

unread,
Oct 7, 2016, 4:05:50 PM10/7/16
to elm-d...@googlegroups.com
On Fri, Oct 7, 2016 at 11:33 AM, Kasey Speakman <kjspe...@gmail.com> wrote: 
Then at the edge of the application, I can deal with the errors
Yes. This is what I am trying to figure out. How to deal with that class of errors at the "edge". 
 
Thanks.

Peter Damoc

unread,
Oct 7, 2016, 5:54:22 PM10/7/16
to Elm Discuss
On Fri, Oct 7, 2016 at 11:02 PM, Dave Ford <df...@smart-soft.com> wrote:
On Fri, Oct 7, 2016 at 11:10 AM, Peter Damoc <pda...@gmail.com> wrote:
If you can come up with a practical scenario where you would have an exception, I or someone else around here could tell you what would happen in Elm in that context.
Yes. The example I gave when I started the thread (sorry for the java syntax - i'm new):

function foo(int x) throws IllegalArgumentException{
  if(x > 10) throw new IllegalArgumentException("Bad x");
  return x * x * x;
}


Doesn't the caller of the function needs to try/catch the exception in Java, in other words, needs to deal with this exception?

In any case, in Elm this function needs to evaluate to something and, since it only works on x smaller than 10, this means that it needs to produce a Maybe Int. 
If you give it something smaller than 10 it produces the Just x*x*x 
If you give it something larger than 10 it should produce Nothing. 

Now, if you need to add 10 to the result of this, you have to choices: 
Either default the result to some value (if that's sensible), OR, you can say... not my business. 

let's imagine a large chain where you have 

add10 = a function that adds 10 to any integer 

multiply3 = a function that multiplies any integer

subtract5 = a function that subtracts 5 

and you want to apply all three to this function that raises to the 3rd power only if x is smaller than 10. 

the way you do it is like this

finalValue = 
    toTheThirdIfSmallerThan10 someValue
    |> Maybe.map (add10 >> multiply3 >> subtract5) 

this will result in a Maybe that has all those functions applied to the result of the toTheThirdIfSmallerThan10 if someValue is smaller than 10 OR Nothing otherwise. 

add10, multiply3 and subtract5 are regular Int->Int functions. 
You don't need to handle the Maybe in each of them. 


Arthur Welf

unread,
Oct 8, 2016, 1:58:15 AM10/8/16
to elm-d...@googlegroups.com
If you want error messages, you can use type Either: 

type Either a b
= Left a
| Right b

You define the set of values which are acceptable as arguments by your function, and they will be executed in the Right branch. Every time your function receives an unacceptable argument, it goes to the Left branch and you can encode for it desired error message for that error. 

You can look at the realisation of the type and functions with this type here: https://github.com/imeckler/either/blob/master/Either.elm 

7 окт. 2016 г., в 4:48, Dave Ford <df...@smart-soft.com> написал(а):

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.

Joey Eremondi

unread,
Oct 8, 2016, 2:36:16 AM10/8/16
to elm-d...@googlegroups.com

Do not use Either. The Result type in the standard library is the same, but with the names more intuitive.


To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.

Martin Janiczek

unread,
Oct 8, 2016, 10:03:39 AM10/8/16
to Elm Discuss
Dave, how do you think about JavaScript Promises? Where you code for the happy path (the chain of Promise.resolve().then().then().then()), any of which can throw, and have a .catch() handler that catches whatever the thrown value was and does something about it.
The Elm Result type is very similar to this.

Promise.resolve(myValue) ~= Ok myValue
Promise.reject(myErrorData) ~= Err myErrorData
promise
.then(fn) ~= myResult.andThen(fn) or myResult.map(fn)
promise
.catch(fn) ~= case myResult of Err x -> fn x


Again, a specific example would help. Elm programs are not written the way C, C#, Java programs are written. Clojure is closer but because of Java interop reasons hasn't adopted much of the Maybe / Result / ... goodness and instead has nils like Java has. In Elm the erorrs are explicit (like you say, part of the return type). Read: http://blog.jenkster.com/2016/06/how-elm-slays-a-ui-antipattern.html for how Elm solves the Server Down error you mentioned.

Malformed JSON is also reported not with exceptions but with Result. Either you get your value in Ok, or helpful error message in Err. You have to handle both cases, it doesn't propagate up, it doesn't throw a runtime exception, the user sees what you decided to show him in that scenario. Essentially the Elm compiler tells you "This could blow up - you told me what to do if the JSON is OK, but what if it is not?"

Zachary Kessin

unread,
Oct 9, 2016, 12:33:47 AM10/9/16
to elm-discuss
Putting on my  Erlang Developer hat (Moto: Let it Crash) I look at it this way there are two kinds .of errors, normal errors an exceptional errors. Lets say you want to go to the store to buy a dozen eggs. There are a few possible outcomes here

1) You get the eggs
2) You can't buy the eggs (Store is out of stock/ no money etc)
3) You can't get to the store because of some kind of Force Major. (IE The store burned down, the police have blocked the street due to an abandoned bag etc)

The elm type system with a Maybe / Result will handle cases #1 and #2. As for case 3, that is a little harder but can still be handled. 

Or to take your examples

  • Invalid function args
  • Malformed JSON
  • Server down
The first one will be handled by the type system. If you try to pass an invalid argument to a function the code will not compile. Obviously there are ways to take run time data and test for validity. You can imagine a function like "parseRomanNumeral : String -> Maybe Int" which takes a string and attempts to treat it as a roman numeral. But the Maybe is there for the case where its not. 

As for the Malformed JSON then you have enforced error handling code. 

In the case of a server down. (As Joe Armstrong said "The best type system will not prevent your server from being struck by lightning" ). Then you get a timeout error which you can handle in some useful way





--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Zach Kessin
Twitter: @zkessin
Skype: zachkessin

John Coady

unread,
Oct 10, 2016, 5:22:02 AM10/10/16
to Elm Discuss


On Friday, 7 October 2016 03:13:32 UTC+1, Dave Ford wrote:
void myFunction(int x){
   if(x < 1){
      throw new IllegalArgumentException("error: x must be >= 1"); 
   }      
   return x * x * x;
}

I look at runtime exceptions as a good thing. It's kind of like having two returns. One return for the normal answer (return). And another for error conditions (throw).

myFunction : Int -> Result String Int
myFunction
=
 
if x < 1 then
    Err "x must be >= 1"
 
else
   
Some x * x * x
 

errorResult
: Result String Int
errorResult
= Result.map (myFunction) (myFunction 0)
-> Err "x must be >= 1"

okResult
: Result String Int
okResult
= Result.map (myFunction) (myFunction 2)
-> Some 64


"Could have a string error" is kept with the type in the same way that "could throw IllegalArgumentException" is.

 

Kasey Speakman

unread,
Oct 10, 2016, 9:23:14 AM10/10/16
to Elm Discuss
Excellent. Then check out this:

Reply all
Reply to author
Forward
0 new messages