Is there a way to compactly write multiple definitions in haskell via case, without having to repeat, other than the input parameters, the exact same syntax? The only possible solution I can imagine so far is a macro.
Below is an example of defining binary max and min functions. Can we compress
max' x y
| x > y = x
| otherwise = y
min' x y
| x < y = x
| otherwise = y
into something like
(max',min') x y
| x (>,<) y = x
| otherwise = y
?
Edit:
I know this allows us to parametrize over the "grumpy face", but it seems like there still could be a more succinct form.
maxmin x y f
| f x y = x
| otherwise = y
max' x y = maxmin x y (>)
min' x y = maxmin x y (<)
Well, you can always do this:
select op x y
| x `op` y = x
| otherwise = y
max' = select (>)
min' = select (<)
I.e. extract the common parts into a function and turn the differences into parameters.
Related
count_instances :: (Int)->([Int])->Int
count_instances x [] = 0
count_instances x (t:ts)
| x==t = 1+(count_instances x ts)
| otherwise = count_instances x ts
i just want to know whats so good about using guards in this Question ?
A guard can be a way to write only one half of an if-then-else expression; you can omit the else and have a partial function.
-- Leave the function undefined for x /= y
foo x y | x == y = ...
You can do the same with a case statement, but it's more verbose
foo x y = case x == y of
True -> ...
It's also easier to list several unrelated conditions as a set of alternatives than it is with a nested if-then-else or case expressions.
foo x y | p1 x y = ...
foo x y | p2 x y = ...
foo x y | p3 x y = ...
foo x y = ...
vs
foo x y = if p1 x y then ...
else (if p2 x y then ...
else (if p3 x y then ... else ...))
Patterns with guards are probably the most concise way to write code that otherwise would require nested case/if expressions.
Not the least advantage is that a where clause applies to all the guards right hand sides. This is why your example could be even more concise:
count_instances :: (Int)->([Int])->Int
count_instances x [] = 0
count_instances x (t:ts)
| x==t = 1+rest
| otherwise = rest
where rest = count_instances x ts
A guard is haskell's most general conditional statement, like if/then/else in other languages.
Your code shows a straight forward implementation of counting contents of a list equal to a given parameter. This is a good example to learn how haskell's recursion works.
An alternative implementation would be
count_instances :: Int -> [Int] -> Int
count_instances i = length . filter (==i)
that reuses already existing functions from the Prelude module. This is shorter and probably more readable.
If I have a function, for example
f :: Int -> Int -> Int
f x y = x + y
and I want to have different functionality based on the parameters, I use pattern matching.
I have only found the syntax of how to match against concrete values, e.g.
f 0 y = y
Is it possible to match against something more general?
I would like to have different functionality in the case that the first parameter is less than 0. A second case could be if the second parameter exceeds a certain value.
You can use guards:
f x y | x < 0 = ...
f x y | y > someValue = ...
f x y | otherwise = ...
Sure, there is a mechanism called guards for that:
f x y | x < 0 = y
The problem:
You are given a function plusOne x = x + 1. Without using any other (+)s, define a recursive function addition such that addition x y adds x and y together.
(from wikibooks.org)
My code (it does not work -- endless loop):
plusOne x = x + 1
addition x y
| x > 0 = addition (plusOne y) (x-1)
| otherwise = y
Questions:
How to connect the plusOne function to the addition recursive function?
How should it be written?
You are mixing up x and y in your recursive case
addition x y | y > 0 = addition (plusOne x) (y - 1) -- x + y == (x + 1) + (y - 1)
| otherwise = x -- x + 0 = x
using == and 0
addition = add 0 where
add a y x | a == y = x
| otherwise = add (plusOne a) y (plusOne x)
Hmm... why does this function ends in an infinite loop when evaluating for any integer > 3?
smallestMultiple n = factors [2..n] where
factors [] = []
factors (h:xs) = h:(factors $ filter ((<)1) [div x h|x<-xs])
where
div x y
|x `mod` y ==0 = x `div` y
|otherwise = x
It appears that the main problem is that you define a local version of div:
div x y
| x `mod` y == 0 = x `div` y
| otherwise = x
Since bindings in where clauses (as well as in let) are recursive, the div on the right hand side of the first case refers to the same div you're defining! You can fix this by using a different name, like div':
div' x y
| x `mod` y == 0 = x `div` y
| otherwise = x
I want to write a Haskell program that calculates the sum of numbers between 2 given numbers.
I have the following code:
sumInt :: Int -> Int -> Int
sumInt x y
| x > y = 0
| otherwise = x + sumInt x+1 y
But when I compile it I get the following error:
SumInt is applied to too few arguments.
I don't understand what I'm doing wrong. Any ideas?
You need parentheses around x+1:
| otherwise = x + sumInt (x + 1) y
The reason is that function application binds more tightly than operators, so whenever you see
f x <> y
This is always parsed as
(f x) <> y
and never as
f (x <> y)