the following code will fail (only) at run time
do {(x:xs) <- return "";return x}
with a user error (Pattern match failure in do expression at ...
Is there a way to enable compiler warnings for this kind of potential errors?
Knowing that some destructive pattern matching might fail , what's the best way to handle this in the general case.
Thank you
Use a case expression instead:
do
case "" of
[] -> undefined -- or whatever else you want to do
(x:xs) -> return x
Hope that helps.
Related
I have a list of Strings, errors. I do some checks and if any fail, I append a message to errors. Something like this:
let errors = []
let errors' = errors ++ if (check1 fails) then ["check1 failed"] else []
let errors'' = errors' ++ if (check2 fails) then ["check2 failed"] else []
Surely there is a more idiomatic way to accumulate changes to errors without making a new variable every time. Do I need to break out Data.IORef for mutable variables? Seems like overkill.
If I simply remove the apostrophes, the compiler returns an error because it gets caught in an infinite loop.
You could group the conditions and messages together
checksTodo = [(check1 fails, "check1 failed"), (check2 fails, "check2 failed")]
errors = map snd (filter fst checksTodo)
If you are comfortable using the list comprehension syntax, you could instead write it in a more readable fashion:
errors = [ msg | (cond, msg) <- checksTodo, cond ]
If I simply remove the apostrophes, the compiler returns an error because it gets caught in an infinite loop.
This is happening because let bindings in Haskell (unlike most languages) are recursive by default. Which means that if you say
let errors = errors ++ if (check1 fails) then ["check1 failed"] else []
the compiler will treat it as a recursive definition. When you try to evaluate errors at runtime, you go into an infinite loop as you need errors to compute errors.
Another alternative:
let errors =
[ "check1 failed" | check1 fails ] ++
[ "check2 failed" | check2 fails ] ++
...
What theindigamer said, plus, the idiomatic way to do error checking is usually having your checker return an Either: if something goes wrong, produce a Left with the error message, otherwise a Right with the result.
Since, in this case, your checks aren't producing an actual result, you can make the result the unit type (); thus, you can convert your checks to generate Either like this:
check1Either = if check1 fails then Left "check1 failed" else Right ()
And then, just run the checks and filter the elements with a Left using the lefts function in Data.Either:
import Data.Either
errors = lefts [check1Either, check2Either]
(You might ask, if there isn't going to be a result to fill Right with, why not use Maybe? You can, and filter errors with catMaybes from Data.Maybe; it's just that Nothing is usually interpreted to mean that the computation failed, and Just usually means success - the opposite of what happens here - whereas, idiomatically speaking Left is usually interpreted as an error)
I was writing a function something similar to this:
f x = let
x = ...
in
e
Due to scoping rules in Haskell any use of x in e will resolve to the definition of x in the let construct.
Why is such a thing allowed in Haskell?
Shouldn't the compiler reject such a program telling we cannot bind a value that has the same name as argument of the function.
(This example may be simplistic, but in real world context where variables have semantic meaning associated with them it is easy to make such mistake)
You can enable warnings for this type of name shadowing with the compiler flag
-fwarn-name-shadowing
This option causes a warning to be emitted whenever an inner-scope value has the same name as an outer-scope value, i.e. the inner value shadows the outer one. This can catch typographical errors that turn into hard-to-find bugs, e.g., in the inadvertent capture of what would be a recursive call in f = ... let f = id in ... f ....
However, it is more common to compile with -Wall, which includes a lot of other warnings that will help you avoid bad practices.
I have a doubt of the Maybe and Either types, and their hypothetical relation to EAFP(Easier Ask Forgiveness to Permission). I've worked with Python and get used to work with the EAFP paradigm in the world of exceptions.
The classical example: Division by zero
def func(x,y):
if not y:
print "ERROR."
else: return (x/y)
and Python's style:
def func(x,y):
try:
return (x/y)
except: return None
In Haskell, the first function would be
func :: (Eq a, Fractional a) => a -> a -> a
func x y = if y==0 then error "ERROR." else x/y
and with Maybe:
func :: (Eq a, Fractional a) => a -> a -> Maybe a
func x y = if y==0 then Nothing else Just (x/y)
In Python's version, you run func without checking y. With Haskell, the story is the opposite: y is checked.
My question:
Formally, does Haskell support the EAFP paradigm or "prefers" LBYL although admits a semi-bizarre EAFP approximation?
PD: I called "semi-bizarre" because, even if it is intuitively readable, it looks (at least for me) like it vulnerates EAFP.
The Haskell style with Maybe and Either forces you to check for the error at some point, but it does not have to be right away. If you don't want to deal with the error now, you can just propagate it on through the rest of your computation.
Taking your hypothetical safe divide-by-0 example, you could use it in a broader computation without an explicit check:
do result <- func a b
let x = result * 10
return x
Here, you don't have to match on the Maybe returned by func: you just extract it into the result variable using do-notation, which automatically propagates failure throughout. The consequence is that you don't need to deal with the potential error immediately, but the final result of the computation is wrapped in Maybe itself.
This means that you can easily combine (compose) functions that miht result in an error without having to check the error at each step.
In a sense, this gives you the best of both worlds. You still only have to check for errors in one place, at the very end, but you're explicit about it. You have to use something like do-notation to take care of the actual propagation and you can't ignore the final error by accident: if you don't want to handle it, you have to turn it into a runtime error explicitly.
Isn't explicit better than implicit?
Now, Haskell also has a system of exceptions for working with runtime errors that you do not have to check at all. This is useful occasionally, but not too often. In Haskell, we only use it for errors that we do not expect to ever catch—truly exceptional situations. The rule of thumb is that a runtime exception represents a bug in your program, while an improper input or merely an uncommon case should be represented with Maybe or Either.
Started working with erlang quite recently and ran into the problem above, how do you go about comparing two strings in a guard statement? Tried the string:equal(x,y) method but couldn't get it to work inside a guard.
You could use pattern matching like this:
are_the_same(A, A) ->
true;
are_the_same(_, _) ->
false.
In first clause both arguments are named A which will result in them being pattern matched against each other. Or to be exact first argument will be bind to A variable with use of = operator, and than second argument will be bind to A variable with = operator, but since A is bound already it will be treated as "comparision". You can read more about this in docs.
And of course you could write write first clouse with use of guard like:
are_the_same(A, B) when A =:= B ->
You don't need the function string:equal/2 to compare strings; you can use the operators == or =:=, which are allowed in guard tests. For example:
foo(A, B) when A =:= B ->
equal;
foo(_, _) ->
not_equal.
Though in most cases you'd want to use pattern matching instead, as described in the other answer.
NB: As of Erlang/OTP 20.0, string:equal(A, B) is no longer equivalent to A =:= B. string:equal/2 now operates on grapheme clusters, and there are also string:equal/3 and string:equal/4 that can optionally ignore case when comparing and do Unicode normalisation. So you need to understand what you mean by "equal" before settling on a comparison method.
The functions you can use in guards are limited because of the nature of Erlang's scheduling; specifically, Erlang aims to avoid side-effects in guard statements (e.g., calling to another process) because guards are evaluated by the scheduler and do not count against reductions. This is why string:equal does not work.
That being said, you can use Erlang's pattern matching to match strings. Please bear in mind the use of strings as lists, binaries, or iolists (nested lists/binaries) in Erlang, and make sure you're testing/passing strings of the right type (iolists are particularly hard to pattern match and are usually best handled with the re module, or converting them to binaries via iolist_to_binary).
For example, say we want a function that tests to see if a string begins with "foo":
bar("foo" ++ _Rest) -> true;
bar(<<"foo", Rest/binary>>) -> true;
bar(_Else) -> false.
If you just want to test for a particular string, it's even easier:
bar("foo") -> true;
bar(<<"foo">>) -> true;
bar(_Else) -> false.
I was trying out the following example given in this tutorial.
What I could not understand is how the case guards for the cases 'c' and _ don't use the on at all?
I modified the code as given here, but then when I run it I got the error "Non-exhaustive patterns in case":
*StateGame> main "accaaaa"
*** Exception: state1.hs:(27,5)-(31,36): Non-exhaustive patterns in case
Why is this so?
A case guard is a boolean expression which is checked after successfully matching the corresponding pattern. If it evaluates to True, that branch is chosen. Otherwise, Haskell will keep trying each case from top to bottom.
In your example, all the cases have the guard expression on:
case x of
'a' | on -> ...
'b' | on -> ...
'c' | on -> ...
_ | on -> ...
Thus, when on is False, none of the branches can be chosen, so you get a "Non-exhaustive patterns in case" exception.