The Haskell compiler throws an error on the following function:
balancedMax :: Int -> Int -> Int
balancedMax -1 _ = -1
balancedMax _ -1 = -1
balancedMax a b = max a b
Flipping the sign solves the problem:
balancedMax :: Int -> Int -> Int
balancedMax 1 _ = -1
balancedMax _ 1 = -1
balancedMax a b = max a b
Why does pattern matching fail on the negatives, and what is a clean workaround?
It fails because it thinks you're trying to re-define the minus operator, because f -1 = ... gets parsed as f - 1 = ....
To fix this you just have to add parentheses:
balancedMax :: Int -> Int -> Int
balancedMax (-1) _ = -1
balancedMax _ (-1) = -1
balancedMax a b = max a b
The same thing happens in expressions. To call balancedMax with a negative literal, you would need parentheses as well.
because f -1 = ... gets parsed as f - 1 = ....
Which if you don't know, means the same thing as:
(-) f 1 = ....
which is similar to defining a function like this:
somefunc x 1 = x + 1
Which happens to be equivalent to defining somefunc() like this:
x `somefunc` 1 = x + 1
It's just that with (-) you don't have to write the backticks when using it in infix position, i.e. positioned between its two arguments.
The two beginning haskell books I've looked at both warn you early on that the unary - needs to be used with parentheses, e.g. (-3).
Related
I am working on the following exercise:
Define a function libDiv which computes the list of natural divisors of some positive integer.
First define libDivInf, such that libDivInf n i is the list of divisors of n which are lesser than or equal to i
libDivInf : int -> int -> int list
For example:
(liDivInf 20 4) = [4;2;1]
(liDivInf 7 5) = [1]
(liDivInf 4 4) = [4;2;1]
Here's is my attempt:
let liDivInf : int -> int -> int list = function
(n,i) -> if i = 0 then [] (*ERROR LINE*)
else
if (n mod i) = 0 (* if n is dividable by i *)
then
i::liDivInf n(i-1)
else
liDivInf n(i-1);;
let liDiv : int -> int list = function
n -> liDivInf n n;;
I get:
ERROR: this pattern matches values of type 'a * 'b ,but a pattern
was expected which matches values of type int
What does this error mean? How can I fix it?
You've stated that the signature of liDivInf needs to be int -> int -> int list. This is a function which takes two curried arguments and returns a list, but then bound that to a function which accepts a single tuple with two ints. And then you've recursively called it in the curried fashion. This is leading to your type error.
The function keyword can only introduce a function which takes a single argument. It is primarily useful when you need to pattern-match on that single argument. The fun keyboard can have multiple arguments specified, but does not allow for pattern-matching the same way.
It is possible to write a function without using either.
let foo = function x -> x + 1
Can just be:
let foo x = x + 1
Similarly:
let foo = function x -> function y -> x + y
Can be written:
let foo x y = x + y
You've also defined a recursive function, but not included the rec keyword. It seems you're looking for something much more like the following slightly modified version of your attempt.
let rec liDivInf n i =
if i = 0 then
[]
else if (n mod i) = 0 then
i::liDivInf n (i-1)
else
liDivInf n (i-1)
I am trying to learn Haskell programming language by trying to figure out some pieces of code.
I have these 2 small functions but I have no idea how to test them on ghci.
What parameters should I use when calling these functions?
total :: (Integer -> Integer) -> Integer -> Integer
total function count = foldr(\x count -> function x + count) 0 [0..count]
The function above is supposed to for the given value n, return f 0 + f 1 + ... + f n.
However when calling the function I don't understand what to put in the f part. n is just an integer, but what is f supposed to be?
iter :: Int -> (a -> a) -> (a -> a)
iter n f
| n > 0 = f . iter (n-1) f
| otherwise = id
iter' :: Int -> (a -> a) -> (a -> a)
iter' n = foldr (.) id . replicate n
This function is supposed to compose the given function f :: a -> a with itself n :: Integer times, e.g., iter 2 f = f . f.
Once again when calling the function I don't understand what to put instead of f as a parameter.
To your first question, you use any value for f such that
f 0 + f 1 + ... + f n
indeed makes sense. You could use any numeric function capable of accepting an Integer argument and returning an Integer value, like (1 +), abs, signum, error "error", (\x -> x^3-x^2+5*x-2), etc.
"Makes sense" here means that the resulting expression has type ("typechecks", in a vernacular), not that it would run without causing an error.
To your second question, any function that returns the same type of value as its argument, like (1+), (2/) etc.
I'm completely lost on this. It was explained that functions are right justified so that let add x y = x + y;; has a function type of int -> int -> int or int -> (int -> int).
I'm not sure how I'd define a function of type (int -> int) -> int. I was thinking I'd have the first argument be a function that passes in an int and returns an int. I've tried:
let add = fun x y -> x + y --- int -> int -> int
let add = fun f x = (f x) + 3 --- ('a -> int) -> 'a -> int
What about
let eval (f: int -> int) :int = f 0
?
fun x -> (x 1) + 1;;
- : (int -> int) -> int = <fun>
or
let foo f = (f 1) + 1;;
val foo : (int -> int) -> int = <fun>
it works like
foo (fun x -> x + 1);;
- : int = 3
Your questions is highly associated with the notion of Currying.
But before that, let me say that if you want to write a function that needs a parameter to be a function, you could declare a normal function, and just use its parameter like a function. No need to complicate it. See the ex:
let f x = x(10) + 10
Now comes the currying part. In OCaml, the parameters are semantically evaluated just one at a time, and after evaluating an argument, an anonymous function is returned. This is important because it lets you supply part of the arguments of a function, creating effectively a new function (which is called Partial Application).
In the example bellow, I use + as a function (parenthesis around an operator turn it to a normal function), to create an increment function. And apply it to the previous f function.
let incr = (+) 1
f incr
The code evaluates to f incr = incr(10) + 10 = 21
This link has more information on the topic applied to OCaml.
I have this code:
esprimo :: Int->Bool
esPrimo x = if length (div x x) == 2 then True else False
But I pulled the error is above
In addition to what sibi said, I think what you are trying to do is this:
isPrime :: Int -> Bool
isPrime x = if length [d | d <- [1..x], x `mod` d == 0] == 2 then True else False
this is basically the direct translation of the mathematical concept of beeing prime into Haskell.
As you don't need the if as it checks the same == already returns a bit more readable might be:
isPrime :: Int -> Bool
isPrime x = length divisors == 2
where divisors = [d | d <- [1..x], x `isMultipleOf` d]
isMultipleOf m n = m `mod` n == 0
Please note that this is of course not the most performant prime-test.
The exact reason for your error is because of the different cases you have used in the type signature and the type definition:
esprimo :: Int -> Bool -- p should be capital here to work.
esPrimo x = if length (div x x) == 2 then True else False
Haskell is case sensitive, so esprimo and esPrimo are different. That being said there is other type error in your code: the type of div is div :: Integral a => a -> a -> a, so it returns a and you are applying length function on it. But length function only accepts list i.e [a] and not a which will produce you type error.
I'm a noob in Haskell, but some experience with ActionScript 3.0 Object Orientated. Thus working on a major programming transition. I've read the basic knowledge about Haskel, like arithmetics. And I can write simple functions.
As a practical assignment I have to generate the Thue-Morse sequence called tms1 by computer in Haskell. So it should be like this:
>tms1 0
0
>tms1 1
1
>tms1 2
10
>tms1 3
1001
>tms1 4
10010110
and so on... According to wikipedia I should use the formula.
t0 = 0
t2n = tn
t2n + 1 = 1 − tn
I have no idea how I can implement this formula in Haskell. Can you guide me to create one?
This is what I got so far:
module ThueMorse where
tms1 :: Int -> Int
tms1 0 = 0
tms1 1 = 1
tms1 2 = 10
tms1 3 = 1001
tms1 x = tms1 ((x-1)) --if x = 4 the output will be 1001, i don't know how to make this in a recursion function
I did some research on the internet and found this code.
Source:
http://pastebin.com/Humyf6Kp
Code:
module ThueMorse where
tms1 :: [Int]
tms1 = buildtms1 [0] 1
where buildtms1 x n
|(n `rem` 2 == 0) = buildtms1 (x++[(x !! (n `div` 2))]) (n+1)
|(n `rem` 2 == 1) = buildtms1 (x++[1- (x !! ((n-1) `div` 2))]) (n+1)
custinv [] = []
custinv x = (1-head x):(custinv (tail x))
tms3 :: [Int]
tms3 = buildtms3 [0] 1
where buildtms3 x n = buildtms3 (x++(custinv x)) (n*2)
intToBinary :: Int -> [Bool]
intToBinary n | (n==0) = []
| (n `rem` 2 ==0) = intToBinary (n `div` 2) ++ [False]
| (n `rem` 2 ==1) = intToBinary (n `div` 2) ++ [True]
amountTrue :: [Bool] -> Int
amountTrue [] = 0
amountTrue (x:xs) | (x==True) = 1+amountTrue(xs)
| (x==False) = amountTrue(xs)
tms4 :: [Int]
tms4= buildtms4 0
where buildtms4 n
|(amountTrue (intToBinary n) `rem` 2 ==0) = 0:(buildtms4 (n+1))
|(amountTrue (intToBinary n) `rem` 2 ==1) = 1:(buildtms4 (n+1))
But this code doesn't give the desired result. Any help is well appreciated.
I would suggest using a list of booleans for your code; then you don't need to explicitly convert the numbers. I use the sequence defined like this:
0
01
0110
01101001
0110100110010110
01101001100101101001011001101001
...
Notice that the leading zeros are quite important!
A recursive definition is now easy:
morse = [False] : map step morse where step a = a ++ map not a
This works because we never access an element that is not yet defined. Printing the list is left as an excercise to the reader.
Here is another definition, using the fact that one can get the next step by replacing 1 with 10 and 0 with 01:
morse = [False] : map (concatMap step) morse where step x = [x,not x]
Edit
Here are easier definitions by sdcvvc using the function iterate. iterate f x returns a list of repeated applications of f to x, starting with no application:
iterate f x = [x,f x,f (f x),f (f (f x)),...]
And here are the definitions:
morse = iterate (\a -> a ++ map not a) [False]
morse = iterate (>>= \x -> [x,not x]) [False]
Your definition of the sequence seems to be as a sequence of bit sequences:
0 1 10 1001 10010110 ... etc.
t0 t1 t2 t3 t4
but the wikipedia page defines it as a single bit sequence:
0 1 1 0 1 ... etc
t0 t1 t2 t3 t4
This is the formulation that the definitions in Wikipedia refer to. With this knowledge, the definition of the recurrence relation that you mentioned is easier to understand:
t0 = 0
t2n = tn
t2n + 1 = 1 − tn
In English, this can be stated as:
The zeroth bit is zero.
For an even, non-zero index, the bit is the same as the bit at half the index.
For an odd index, the bit is 1 minus the bit at half the (index minus one).
The tricky part is going from subscripts 2n and 2n+1 to odd and even, and understanding what n means in each case. Once that is done, it is straightforward to write a function that computes the *n*th bit of the sequence:
lookupMorse :: Int -> Int
lookupMorse 0 = 0;
lookupMorse n | even n = lookupMorse (div n 2)
| otherwise = 1 - lookupMorse (div (n-1) 2)
If you want the whole sequence, map lookupMorse over the non-negative integers:
morse :: [Int]
morse = map lookupMorse [0..]
This is the infinite Thue-Morse sequence. To show it, take a few of them, turn them into strings, and concatenate the resulting sequence:
>concatMap show $ take 10 morse
"0110100110"
Finally, if you want to use the "sequence of bit sequences" definition, you need to first drop some bits from the sequence, and then take some. The number to drop is the same as the number to take, except for the zero-index case:
lookupMorseAlternate :: Int -> [Int]
lookupMorseAlternate 0 = take 1 morse
lookupMorseAlternate n = take len $ drop len morse
where
len = 2 ^ (n-1)
This gives rise to the alternative sequence definition:
morseAlternate :: [[Int]]
morseAlternate = map lookupMorseAlternate [0..]
which you can use like this:
>concatMap show $ lookupMorseAlternate 4
"10010110"
>map (concatMap show) $ take 5 morseAlternate
["0", "1", "10", "1001", "10010110"]
Easy like this:
invertList :: [Integer] -> [Integer]
invertList [] = []
invertList (h:t)
|h == 1 = 0:invertList t
|h == 0 = 1:invertList t
|otherwise = error "Wrong Parameters: Should be 0 or 1"
thueMorse :: Integer -> [Integer]
thueMorse 1 = [0]
thueMorse n = thueMorse (n - 1) ++ invertList (thueMorse (n - 1))