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
Related
So, I have been trying to use SDL to make a simple GUI. This is so that I start to understand how to use haskell. In this case, I was using https://github.com/palf/haskell-sdl2-examples/blob/master/examples/lesson04/src/Lesson04.hs as reference.
Pay attention, in particular to payloadToIntent on line 72.
payloadToIntent :: SDL.EventPayload -> Intent
payloadToIntent SDL.QuitEvent = Quit
payloadToIntent (SDL.KeyboardEvent k) = getKey k
payloadToIntent _ = Idle
This works perfectly. However, when I change the code to the following, it produces an error. Why does it happen, as to my (admittedtly novice) eyes, this looks equivalent.
payloadToIntent e
| e == SDL.QuitEvent = Quit
| e == SDL.KeyboardEvent k = getKey SDL.KeyboardEvent k
| otherwise = Idle
Error:
src/Events/Intent.hs:15:28: error:
Variable not in scope: k :: SDL.KeyboardEventData
|
15 | | e == SDL.KeyboardEvent k = getKey SDL.KeyboardEvent
| ^
I am using these language extensions: OverloadedStrings, GADTs, PatternGuards
So why did this happen? How could I fix this? Which one would be more idiomatic haskell?
(==) is a function that takes two values of the same type and compares them for equality, returning a Bool. SDL.KeyboardEvent k is not a value of any type (since k is unbound), so you can't compare it with (==).
The idiomatic "choice" is the one that works, i.e. pattern matching. If you want something that has a similar appearance, you can pattern match with case...of instead:
payloadToIntent e = case e of
SDL.QuitEvent -> Quit
SDL.KeyboardEvent k -> getKey k
_ -> Idle
The key idea here is: patterns define variables, bringing them into scope, while expressions do not, requiring all the variables in them to be already defined.
The guard e == SDL.KeyboardEvent k is a boolean valued expression, not a pattern. This is calling function (==) with two arguments: e and SDL.KeyboardEvent k. Your definition, to the compiler, looks like:
payloadToIntent e
| isEqual e SDL.QuitEvent = Quit
| isEqual e (SDL.KeyboardEvent k) = getKey SDL.KeyboardEvent k
| otherwise = Idle
The compiler can not call the equality-test function without passing it the arguments. For that, it needs variable k to be in scope, i.e., to be defined somewhere else.
To stress the point, consider this non-working code:
isSquare :: Int -> String
isSquare n | n == m*m = "It's the square of " ++ show m
| otherwise = "It isn't a square"
This would magically invert the squaring, if possible. That is, however, asking too much to the compiler, which won't magically solve the equation for us. (Indeed, the solution could even fail to be unique!)
As an even more cumbersome case:
f x | x == F y || x == G z = ...
Even if this worked, can we use y or z in the final ...? Probably not. Why should then this be allowed?
Finally, note that, even in those cases where it could work, allowing expressions guards to define variables could be a bad idea. Consider this:
c :: Int
c = 7
f x | x == F c = "Hi"
| otherwise = "there"
Now, is the c in F c a new local variable which is defined on the spot, or is it the constant 7 defined above? If we call f (F 6) do we get Hi (c was a new variable) or there (c was 7)?
Pattern matching avoids this issue by requiring a distinct syntax.
First of all, I want to say that I'm very very inexperienced with Haskell, and I know that I have done something (or multiple things) terribly wrong, been struggling for hours but I can't seem to find it.
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
list = replicate y x
foldr (*) x list
main = print $ power 3 5
Error most of the time is either x and y not being passed to the replicate function or that foldr is a naked function, I understand what they both mean but have no idea on how I can pass the variables or come up with a solution.
You here created four functions: power, list, foldr and main. But you use variables x and y in the definition of the list function.
You can work with a where clause to specify subexpressions, for example:
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) 1 list
where list = replicate y x
or perhaps more elegant with pattern matching:
power :: Int -> Int -> Int
power 0 _ = 0
power x y = foldr (*) 1 (replicate y x)
main = print $ power 3 5
Here we can also eliminate the case for x0, since our foldr starts working with 1, not x.
This algorithm is however not very efficient, since it is linear in the value of y. By checking recursively if the exponent is even or odd, you can make it faster. I leave this as an exercise.
You were very close! The main things that need to be fixed are:
When writing a definition with guards, the “fallback” case needs to be a guard as well, conventionally written with otherwise.
Recall that a definition without guards looks like this, with one left side (a name and parameter patterns/names) and one right side (an expression):
name patterns = expression
With guard conditions, there is one right-hand side for each guard:
name patterns | condition1 = expression1
| condition2 = expression2
…
| otherwise = expressionn
otherwise is really just an alias for True, that is, such a guard always matches. The only thing special about otherwise is that the compiler uses it as a hint when analysing whether a pattern match covers all possible cases.
In order to define a variable list, local to the definition of power, using the parameters x and y, you need to use either a let…in… expression, that is, let block in expression, or a where clause, equation where block. A block is a series of items (in this case, local definitions) which must all be written starting at the same column of indentation, or be delimited by explicit curly braces {…} and semicolons ;.
Using let…in… follows the structure of your original code pretty closely. I will adjust the indentation style to avoid needing to align anything, by putting a newline and a constant amount of indentation instead.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let
list = replicate y x
in foldr (*) x list
main :: IO ()
main = print $ power 3 5
Attaching a where clause to an equation is slightly more common than using a let…in… expression on the right side of an equation.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) x list
where
list = replicate y x
main :: IO ()
main = print $ power 3 5
Note that in this case, there is a slight difference: the variable list is visible in all of the right-hand sides, although we only use it in one of them. With let list = … in e, list is only defined within e. In general, it’s helpful for readability to keep the scope of a variable as small as possible, although you can certainly go overboard:
a = …
where
b = …
where
c = …
where
d = …
-- If you see this much nesting, rethink!
If you run into issues with alignment and indentation, you can always use explicit delimiters instead. The code I wrote is equivalent to the following.
power :: Int -> Int -> Int; -- Begin ‘power’ signature.
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let { -- Begin ‘let’ block.
list = replicate y x; -- End ‘list’ equation.
} in foldr (*) x list; -- End ‘let’ block, then end ‘power’ equation.
main :: IO (); -- Begin ‘main’ signature.
main = print $ power 3 5; -- End ‘main’ equation.
Or similarly with where { … }.
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
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.
I get input (x) from user, convert it to Int by let y = (read x)::Int and then I would like the function to behave in a special way if user gave nothing (empty string).
-- In this place I would like to handle situation in which user
-- gave empty string as argument
-- this doesnt work :/
yearFilter [] y = True
--This works fine as far as y is integer
yearFilter x y | x == (objectYear y) = True
| otherwise = False
Thanks for help,
Bye
Perhaps you want a Maybe type? If the user enters the empty string, your function returns Nothing; otherwise it returns Just n, where n is what's entered by the user?
userInt :: String -> Maybe Int
userInt [] = Nothing
userInt s = Just $ read s
(I haven't compiled this code.)
In this case, Maybe may not suffice: You have three conditions to worry about:
The user entered nothing
The user input was valid
The user input was unparsable
This data type and function express this directly:
data Input a = NoInput | Input a | BadInput String
deriving (Eq, Show)
input :: (Read a) => String -> Input a
input "" = NoInput
input s =
case filter (null.snd) (reads s) of
((a,_):_) -> Input a
otherwise -> BadInput s
Note that rather than using the incomplete function read, it uses reads which will not error on input which cannot be converted. reads has a somewhat awkward interface, alas, so I almost always end up wrapping it in a function that returns Maybe a or something like this here.
Example use:
> input "42" :: Input Int
Input 42
> input "cat" :: Input Int
BadInput "cat"
> input "" :: Input Int
NoInput
I would code your yearFilter function like this:
yearFilter :: Maybe Int -> Int -> Bool
yearFilter Nothing _ = True
yearFilter (Just x) y = x == objectYear y
Then I'd handle user input as:
inputToMaybe :: Input a -> Maybe a
inputToMaybe (Input a) = Just a
inputToMaybe _ = Nothing
do
a <- input `fmap` getLine
case a of
BadInput s -> putStrLn ("Didn't understand " ++ show s)
otherwise -> ... yearFilter (inputToMaybe a) ....
N.B.: I've cleaned up the code in yearFilter a bit: no need to use guards to produce a boolean from a test - just return the test, function application (objectYear) binds tighter than operators (==) so removed parenthesis, replaced names of unused inputs with _.
Okay, I admit I can't help myself.... I've rewritten yearFilter yet again, this time as I would be inclined to write it:
yearFilter :: Maybe Int -> Int -> Bool
yearFilter x y = maybe True (== objectYear y) x
Learning about Maybe and maybe was first thing about Haskell that really made me love the language.
There is no NULL unless you explicitly define it. You could check for empty strings like this.
readInput :: IO ()
readInput = do
ln <- getLine
if valid ln
then -- whatever
else -- whatever
valid x
| null x = False
| not istJust convert x = False
| otherwise = True
where convert :: String -> Maybe Int
convert = fmap fst $ listToMaybe . reads $ "f"
The 'read' function cannot convert an empty string to an int, and will cause an error if you try to do so. You'll need to test whether the input is an empty string before converting to int. If you want to use a default value (such as 0) in the event that the user enters an empty string, you could do something like this:
let y = if null x then 0 else read x