I think there are two common approaches:

1) Deal with the Maybe at a different level.  You mentioned having a deep
call stack, and not wanting to pass a Maybe Int throughout, so maybe
somewhere in the stack it makes sense to give a default value.  Even though
you know you have a non-empty list, it's likely that in certain contexts
you *could* intelligibly deal with empty lists.  Perhaps at a certain level
there's an obvious default.  For example, maybe at a relatively low level,
it makes sense to default to zero if there are no items.  Or if not, maybe
you use the Int to make a String, and maybe it makes sense to default to
the empty string or a placeholder if there's no max.  Or if not, maybe the
string is used in some Html and maybe it makes sense to show a different
thing if there's no String.

If there are any levels that have an obvious default, I think it can also
improve the modularity and reusability of your code to implement those
defaults even though you know in reality that code path will never get
executed.

2) You said you had a provably non-empty list, so why not make a
NonEmptyList type to represent that instead of using List.  Then you could
make `NonEmptyList.maximum : NonEmptyList Int -> Int` and not have to worry
about Maybes.

On Sun, Aug 20, 2017 at 1:12 PM, Dave Doty <pexa...@gmail.com> wrote:

> I have found many situations in which I am forced by the compiler to deal
> with a situation that will never come up at runtime (or, if it does come
> up, it's a bug in my code and not something the user can do to fix). For
> example, I might make a provably non-empty List (e.g., it is always made
> by the :: operator) and later ask for its max value:
>
> max: List Int -> Int
> max list =
> case List.maximum list of
>     Just v ->
>         v
>
>     Nothing ->
>         Debug.crash "This should be unreachable."
>
> The "standard" way to handle this would be to make max return a Maybe or
> a Result instead (i.e., just use List.maximum directly), but this can
> have the effect of altering the type signature of several other functions,
> all for an error that represents a bug in my program, not something caused
> by user error that the user needs to be alerted about. This might be 10
> levels deep into a function call, and it seems dumb to change the type
> signature of every function from max all the way back up to the top to
> return Maybe, just to handle the situation (list is empty) that can only
> arise through programmer error, not user error.
>
> Is there an "standard" way of dealing with situations like this? I assume
> it's not Debug.crash, given the ample warnings against using it in
> production code. But despite the advertisements of "no runtime exceptions
> in practice", sometimes it seems that there really is no graceful way to
> handle programming errors other than to tell the user there's a bug in the
> code, and dump a stack trace so that the bug can be tracked down. In other
> words, a runtime exception seems like it does exactly what is needed in
> this situation.
>
> --
> 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+unsubscr...@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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to