Haskell - guard inside case statement - haskell

I am going through Learn you a haskell book, and in Chapter 8 there is a snippet of code which looks like this
data LockerState = Taken | Free deriving (Eq, Show)
type Code = String
type LockerMap = Map.Map Int (LockerState, Code)
lookup' :: Int -> LockerMap -> Either String Code
lookup' num_ map_ =
case (Map.lookup num_ map_) of
Nothing -> Left $ "LockerNumber doesn't exist!"
Just (state, code) -> if state == Taken
then Left $ "LockerNumber already taken!"
else Right $ code
This works. However, I wanted to convert if/else block to guard statements like this:
lookup' :: Int -> LockerMap -> Either String Code
lookup' num_ map_ =
case (Map.lookup num_ map_) of
Nothing -> Left $ "LockerNumber doesn't exist!"
Just (state, code) ->
| state == Taken = Left $ "LockerNumber already taken!"
| otherwise = Right $ Code
This doesn't compile. It seems that usage of guards in Haskell is very restrictive/non intuitive. SO Ex1 SO Ex2. Is there a definite source which I can read which tells at which places I can use guards?

There are two places guards are allowed: function definitions and case expressions. In both contexts, guards appear after a pattern and before the body, so you use = in functions and -> in case branches, as usual:
divide x y
| y == 0 = Nothing
--------
| otherwise = Just (x / y)
-----------
positively mx = case mx of
Just x | x > 0 -> Just x
-------
_ -> Nothing
Guards are simply constraints for patterns, so Just x matches any non-Nothing value, but Just x | x > 0 only matches a Just whose wrapped value is also positive.
I suppose the definitive reference is the Haskell Report, specifically §3.13 Case Expressions and §4.4.3 Function and Pattern Bindings, which describe the syntax of guards and specify where they’re allowed.
In your code, you want:
Just (state, code)
| state == Taken -> Left "LockerNumber already taken!"
| otherwise -> Right code
This is also expressible with patterns alone:
Just (Taken, _) -> Left "LockerNumber already taken!"
Just (_, code) -> Right code

Related

Simulating non-deterministic choice through the List Monad

I'm trying to write an evaluation function for a language that I am working on in which non-determinism can be permitted within an if-block, called a selection block. What I'm trying to achieve is the ability to pick an if/selection statement from the block whose guard is true and evaluate it but it doesn't matter which one I pick.
From searching, I found an example that performs in a similar way to what I would like to achieve through modelling coinflips. Below is my adapation of it but I'm having issue in applying this logic to my problem.
import Control.Monad
data BranchType = Valid | Invalid deriving (Show)
data Branch = If (Bool, Integer) deriving (Show, Eq)
f Valid = [If (True, 1)]
f Invalid = [If (False, 0)]
pick = [Invalid, Invalid, Valid, Invalid, Valid]
experiment = do
b <- pick
r <- f b
guard $ fstB r
return r
s = take 1 experiment
fstB :: Branch -> Bool
fstB (If (cond, int)) = cond
main :: IO ()
main = putStrLn $ show $ s -- shows first branch which could be taken.
Below is my ADT and what I have been trying to make work:
data HStatement
= Eval HVal
| Print HVal
| Skip String
| Do HVal [HStatement]
| If (HVal, [HStatement])
| IfBlock [HStatement] -- made up of many If
| Select [HStatement] -- made up of many If
deriving (Eq, Read)
fstIf :: HStatement -> Bool
fstIf (If (cond, body)) = if hval2bool cond == True
then True
else False
h :: Env -> HStatement -> IOThrowsError ()
h env sb = do
x <- g env sb
guard $ fstIf x -- Couldn't match expected type ‘HStatement’ with actual type ‘[HStatement]’
-- after guard, take 1 x then evaluate
g :: Env -> HStatement -> IOThrowsError [HStatement]
g env (Select sb) = mapM (\x -> f env x) sb
f :: Env -> HStatement -> IOThrowsError HStatement
f env (If (cond, body)) = evalHVal env cond >>= \x -> case x of
Bool True -> return $ If (Bool True, body)
Bool False -> return $ If (Bool False, body)
The error I receive is the following : Couldn't match expected type ‘HStatement’ with actual type ‘[HStatement]’ at the guard line. I believe the reason as to why the first section of code was successful was because the values were being drawn from List but in the second case although they're being drawn from a list, they're being drawn from a [HStatement], not something that just represents a list...if that makes any sort of sense, I feel like I'm missing the vocabulary.
In essence then what should occur is given a selection block of n statement, a subset of these are produced whose guards are true and only one statement is taken from it.
The error message is pretty clear now that you have some types written down. g returns IOThrowsError [HStatement], so when you bind its result to x in h, you have an [HStatement]. You then call fstIf, which expects a single HStatement, not a list. You need to decide how to handle the multiple results from g.

func :: Maybe(Int) -> Maybe(Int)

I've done some research but couldn't find anything. I don't understand how a function like this works:
func :: Maybe (Int) -> Maybe (Int)
How am I supposed to do the pattern matching? I've tried this but it didn't work:
func Just a = Just a | otherwise = Nothing
func Nothing = Just Nothing | otherwise = Nothing
How can I make this work?
Error message:
exercises6.hs:83:22: error: parse error on input ‘|’
|
83 | func Just a = Just a | otherwise = Nothing
| ^
You pattern match on the two possible cases. A Maybe a has two data constructors: a Nothing, and a Just … with … the value it wraps. There is no | otherwise part when you do pattern matching. The pipe character (|) is used for guards [lyah].
So you can for example increment the value in a Just with:
func :: Maybe Int -> Maybe Int
func (Just x) = Just (x+1)
func Nothing = Nothing
The brackets around Just x are required here, as #chepner says. Otherwise it will be parsed as if Just is the first parameter, and x is a second parameter.
Since Maybe is an instance of the Functor typeclass, you can make use of fmap :: Functor f => (a -> b) -> f a -> f b here:
func :: Maybe Int -> Maybe Int
func = fmap (1+)

haskell wikibook monadplus potential error

Was reading monadplus chapter of haskell wiki book: https://en.wikibooks.org/wiki/Haskell/MonadPlus
digit :: Int -> String -> Maybe Int
digit i s | i > 9 || i < 0 = Nothing
| otherwise = do
let (c:_) = s
if [c] == show i then Just i else Nothing
"The do-block assures that any failed pattern match will result in returning Nothing."
However, when I tried digit 1 "", it produces irrefutable runtime error, instead of "Nothing".
I can get around it using (c:_) <- return s. It would be great if someone more experienced in haskell could confirm/clarify on this.
The code in wikibooks does not account for the case when the input string is empty. When the line let (c:_) = s is executed and s is empty, it will cause a failure in the pattern matching and an exception will be thrown. Your suggestion (c:_) <- return s is actually quite similar to the one used, except for one difference; when the pattern matching in a monadic bind (i.e. <-) fails, then the fail method of the monad will be called. Now, in the Maybe monad, fail is defined to always return Nothing,so it will cause the whole do block to return Nothing. One thing I don't like about using your suggestion is that I personally don't consider using fail to be the most elegant solution and I would prefer to use a case expression in the case:
digit :: Int -> String -> Maybe Int
digit i s | i > 9 || i < 0 = Nothing
| otherwise =
case s of
c:_ | [c] == show i -> Just i
_ -> Nothing
In fact, as you can see, we don't need to use a do block at all.
Finally, here's a more compact version of the above code:
digit :: Int -> String -> Maybe Int
digit i s | 0 <= i, i <= 9, c:_ <- s, [c] == show i = Just i
| otherwise = Nothing

In Haskell, are guards or matchers preferable?

I'm learning Haskell, and it's not always clear to me when to use a matcher and when to use a guard. For certain scenarios it seems that matchers and guards can be used to achieve essentially the same ends. Are there some rules or heuristics for when it's better to use matches over guards or vice versa? Is one more performant than the other?
To illustrate what I'm getting at, here are a couple of silly examples I cooked up that seem to be equivalent, but one version uses matchers and the other uses guards:
listcheck :: [a] -> String
listcheck [] = "List is null :-("
listcheck a = "List is NOT null!!"
listcheck' a
| null a = "List is null :-("
| otherwise = "List is NOT null!!"
and
luckyseven :: Int -> String
luckyseven 7 = "SO LUCKY!"
luckyseven b = "Not so lucky :-/"
luckyseven' c
| c == 7 = "SO LUCKY!"
luckyseven' c = "Not so lucky :-/"
Thanks!
These can often be used interchangeably, but there are significant differences between the two. Pattern matching can only occur on constructors, so computations can not be performed inside of a pattern, while guards are simply multi-branch if-else statements. For example, I can't write a pattern equivalent of the following:
func :: Int -> Int
func x
| even x = 3 * x
| odd x = 7 * x -- alternatively "otherwise = 7 * x" to get rid of all those pesky compiler warnings
This just wouldn't be possible with just pattern matching. You also can't do things like
func :: Int -> Maybe String
func x
| x < 0 = Nothing
| x == 0 = Just "Zero"
| x < 20 = Just "Small"
| x < 100 = Just "Big"
| x < 1000 = Just "Huge"
| otherwise = Just "How did you count that high?"
Conversely, guards using ADTs don't give you much information without helper functions. If I had the type
data Expr
= Literal Int
| Add Expr Expr
| Mult Expr Expr
| Negate Expr
deriving (Eq, Show)
Using guards to write the equivalent of
eval :: Expr -> Int
eval (Literal i) = i
eval (Add e1 e2) = eval e1 + eval e2
eval (Mult e1 e2) = eval e1 * eval e2
eval (Negate e) = negate (eval e)
would be a lot more verbose, difficult, and annoying. In fact, at some level you'd have to resort to pattern matching to do things like
getLiteral :: Expr -> Int
getLiteral (Literal i) = i
getLiteral _ = error "Not a literal"
Which introduces functions that can error, which is bad. In this case, using pattern matching is much preferred over using guards.
For your particular examples, I'd go with pattern matching, but would use _ where possible:
listCheck :: [a] -> String
listCheck [] = "List is null :-("
listCheck _ = "List is NOT null!!"
and
luckySeven :: Int -> String
luckySeven 7 = "SO LUCKY!"
luckySeven _ = "Not so lucky :-/"
That emphasizes that if the list isn't empty, or the Int isn't 7, nothing else matters, and you aren't going to use its particular value to produce the function result. bheklilr has capably pointed out places where one choice or the other is definitely preferable.

guard desugaring

I often hear the phrase, guards are just syntactic sugar for if-then-else (or case statements).
Can somebody please desugar the following instance:
halfOf :: Int -> Int
halfOf x | even x = div x 2
(The function is intentionally partial)
Thanks,
halfOf x =
if even x
then div x 2
else error "Incomplete pattern match"
The exact kind of error triggered by an unhandled case is not specified by the language definition, and varies from compiler to compiler.
edit: If there are multiple guards and/or patterns, each guard or pattern match goes into the non-matching part of the previous case.
compare x y
| x == y = foo
| x /= y = bar
compare _ _ = baz
produces
compare x y =
if x == y
then foo
else if x /= y
then bar
else baz
The semantics of pattern matching are defined in the following section of the standard: Formal Semantics of Pattern Matching.
The step that is relevant to your question is c. As you can see, pattern matches with guards of the form
case v of { p | g1 -> e1 ; ...
| gn -> en where { decls }
_ -> e' }
Are translated to pattern matches without guards as:
case e' of
{y ->
case v of {
p -> let { decls } in
if g1 then e1 ... else if gn then en else y ;
_ -> y }}
So pattern guards are defined in terms of if and "fallthrough" is implemented by binding the expression to a variable and then repeating it once in the else clause of the if and then in the pattern that you'd fall through to.
If there is no case to fall through to (as in your example) one will have been inserted by step b, which inserts a default case _ -> error "No match"

Resources