Haskell - Guards or if-then-else?

Started by
4 comments, last by Anonymous P 15 years, 6 months ago
Is one of these considered more idiomatic than the other?:
-- With guards
func a
  | pred a = Just a      -- some comment here
  | otherwise = Nothing


-- With if-then-else (just one possible arrangement)
func a = if pred a
         then Just a     -- some comment here
         else Nothing
I'm never really sure which to prefer. I like the former myself but I'd rather code in a way that's best for the majority of potential readers.
Advertisement
The former is idiomatic. if/then/else is a much less common construction in languages with algebraic types and pattern matching than it is in languages without them.
Thank you, I'm quite pleased to hear that actually.

I've just submitted my first ever Haskell program as my functional programming assignment. I might post the code later for critiquing as I'm doubtful I'll get feedback on it before my second assignment is due. I'll probably start a new thread for that.
In erlang you would use case:

a(X) ->
case X of
X -> true; // matches X returns "true"
_ -> nothing // matches anything else, returns "nothing"
end.

What's the point of an erlang guard?

a(X,Y) ->
if
X>Y -> X; // the guard checks for an eval of "true" returns X
Y>X -> Y; // the guard checks for an eval of "true" returns Y
true -> nothing // the atom "true" always evals to "true" returns "nothing"
end.
If this function is very general-purpose, you might want to generalize its type a bit:

import Control.MonadreturnWhen :: MonadPlus m => Bool -> t -> m treturnWhen cond val = guard cond >> return valfunc a = returnWhen (pred a) a


This works in the Maybe monad (returns Just a or Nothing), the List monad (returns [a] or []), the IO monad (returns a or throws an exception), etc.
When there are guards available, use them.

Quote:In erlang you would use case:
a(X) ->case X ofX -> true; // matches X returns "true"_ -> nothing // matches anything else, returns "nothing"end.

No.

You either

a) don't know erlang from your elbow or

b) are posting nonsense on purpose for some reason.

That code returns true in all cases: it is equivalent to the function

a(_) -> true. 


as a bound variable will always match itself. Any self-respecting erlang compiler will warn you of this, too: it's so nonsensical even the compiler can catch it!

Not to mention that double slashes are not valid erlang comment delimiters.

Lastly, it has nothing to do with guards.

In erlang, you would use guards if your predicate is a built-in function or an operator (this is because the compiler needs to guarantee termination and side-effect freedom of pattern expressions, which guards are) or you'd use case if your predicate was defined by yourself.

For example, if your predicate is the builtin function is_integer, you'd write your function like so:

a(X) when is_integer(X) ->	{just, X};a(_) ->	nothing.


and if it's a predicate defined by yourself (thus the compiler can't establish its side-effect freedom and termination) you might write it like this:

b(X) ->	case pred(X) of		true ->			{just, X};		_ ->			nothing	end.

This topic is closed to new replies.

Advertisement