myfunc:: [Int] -> Int -> Int
myfunc mylist i =
if length(mylist) == 0 then 1
else
(head(mylist) * i) + myfunc((tail(mylist)) (i+1))
I want to get a weighted sum over a list.
for example, at given parameter [10,9,8,7,6] and 1,
I want to get 10*1 + 9*2 + 8*3 + 7*4 + 6*5 ..
But my code puts error that
test.hs:9:18: error:
• Couldn't match expected type ‘Int’ with actual type ‘Int -> Int’
how to fix this problem??
you should check your parentheses - you use much more of them then you need to (leading to the problem here)
If you look at myfunc((tail(mylist)) (i+1)) then if you count the (..) you will see that the one argument to myfunc here is tail(mylist) (i+1) but this would mean that you try to apply (i+1) to tail(mylist)
Also instead of the check with length and head you can use pattern-matching.
here is a cleaned up version of your function:
myfunc :: [Int] -> Int -> Int
myfunc [] _ = 1
myfunc (h:tl) i = h*i + myfunc tl (i+1)
which will return 111 for your example:
> myfunc [10,9,8,7,6] 1
111
I don't know how much you've seen of Haskell but you can express this as
myfunc :: [Int] -> Int -> Int
myfunc weights start = 1 + sum (zipWith (*) weights [start..])
too - which I would consider more readable and idiomatic
Also: - why the 1 if the list is empty? Shouldn't your weighted sum be 0 if the list is empty??
Related
I wrote my first program in Haskell today. It compiles and runs successfully. And since it is not a typical "Hello World" program, it in fact does much more than that, so please congrats me :D
Anyway, I've few doubts regarding my code, and the syntax in Haskell.
Problem:
My program reads an integer N from the standard input and then, for each integer i in the range [1,N], it prints whether i is a prime number or not. Currently it doesn't check for input error. :-)
Solution: (also doubts/questions)
To solve the problem, I wrote this function to test primality of an integer:
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
It works great. But my doubt is that the first line is a result of many hit-and-trials, as what I read in this tutorial didn't work, and gave this error (I suppose this is an error, though it doesn't say so):
prime.hs:9:13:
Type constructor `Integer' used as a class
In the type signature for `is_prime':
is_prime :: Integer a => a -> Bool
According to the tutorial (which is a nicely-written tutorial, by the way), the first line should be: (the tutorial says (Integral a) => a -> String, so I thought (Integer a) => a -> Bool should work as well.)
is_prime :: (Integer a) => a -> Bool
which doesn't work, and gives the above posted error (?).
And why does it not work? What is the difference between this line (which doesn't work) and the line (which works)?
Also, what is the idiomatic way to loop through 1 to N? I'm not completely satisfied with the loop in my code. Please suggest improvements. Here is my code:
--read_int function
read_int :: IO Integer
read_int = do
line <- getLine
readIO line
--is_prime function
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
main = do
n <- read_int
dump 1 n
where
dump i x = do
putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
if i >= x
then putStrLn ("")
else do
dump (i+1) x
You are misreading the tutorial. It would say the type signature should be
is_prime :: (Integral a) => a -> Bool
-- NOT Integer a
These are different types:
Integer -> Bool
This is a function that takes a value of type Integer and gives back a value of type Bool.
Integral a => a -> Bool
This is a function that takes a value of type a and gives back a value of type Bool.
What is a? It can be any type of the caller's choice that implements the Integral type class, such as Integer or Int.
(And the difference between Int and Integer? The latter can represent an integer of any magnitude, the former wraps around eventually, similar to ints in C/Java/etc.)
The idiomatic way to loop depends on what your loop does: it will either be a map, a fold, or a filter.
Your loop in main is a map, and because you're doing i/o in your loop, you need to use mapM_.
let dump i = putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
in mapM_ dump [1..n]
Meanwhile, your loop in is_prime is a fold (specifically all in this case):
is_prime :: Integer -> Bool
is_prime n = all nondivisor [2 .. n `div` 2]
where
nondivisor :: Integer -> Bool
nondivisor i = mod n i > 0
(And on a minor point of style, it's conventional in Haskell to use names like isPrime instead of names like is_prime.)
Part 1: If you look at the tutorial again, you'll notice that it actually gives type signatures in the following forms:
isPrime :: Integer -> Bool
-- or
isPrime :: Integral a => a -> Bool
isPrime :: (Integral a) => a -> Bool -- equivalent
Here, Integer is the name of a concrete type (has an actual representation) and Integral is the name of a class of types. The Integer type is a member of the Integral class.
The constraint Integral a means that whatever type a happens to be, a has to be a member of the Integral class.
Part 2: There are plenty of ways to write such a function. Your recursive definition looks fine (although you might want to use n < i * i instead of n < 2 * i, since it's faster).
If you're learning Haskell, you'll probably want to try writing it using higher-order functions or list comprehensions. Something like:
module Main (main) where
import Control.Monad (forM_)
isPrime :: Integer -> Bool
isPrime n = all (\i -> (n `rem` i) /= 0) $ takeWhile (\i -> i^2 <= n) [2..]
main :: IO ()
main = do n <- readLn
forM_ [1..n] $ \i ->
putStrLn (show (i) ++ " is a prime? " ++ show (isPrime i))
It is Integral a, not Integer a. See http://www.haskell.org/haskellwiki/Converting_numbers.
map and friends is how you loop in Haskell. This is how I would re-write the loop:
main :: IO ()
main = do
n <- read_int
mapM_ tell_prime [1..n]
where tell_prime i = putStrLn (show i ++ " is a prime? " ++ show (is_prime i))
I'm having an issue that is frustrating me a bit. I have the next really simple code:
describe "functions" $ do
it "can create a function" $ do
mysum :: a -> a
let mysum x = x + 1
mysum 5
But is not compiling, the error I'm having is:
error: Variable not in scope: mysum :: a -> a
|
15 | mysum :: a -> a
From the books I'm reading seems everything fine to me, and in internet seems that shouldn't fail my code, am I missing something?
Also I tried more alternatives:
let b = mysum :: a -> a
let b x = x + 1
b 5
And
let b = a -> a
let b x = x + 1
b 5
But in all of them I have errors
To define a function with a signature in a do-block, you need to put both its signature and its definition inside the same let. Indentation matters. For instance,
example = do
something1
something2
let mysum :: Num a => a -> a
mysum x = x + 1 -- same indentation as "mysum" above
something3 -- we can use mysum here
something4
Concretely:
describe "functions" $ do
it "can create a function" $ do
let mysum :: Num a => a -> a
mysum x = x + 1
mysum 5 `shouldBe` (6 :: Int)
The above declares a polymorphic mysum, as you tried to do. If we instead define a more basic mysum :: Int -> Int, we do not need to specify that 6 is an Int in the very last line, since that's already deduced.
I want to write a function which prints out a list of numbers from 1 to n: [1,2,...n], I know it can be done by [1..n] but I want to make my own function:
addtimes n = addtimes_ [] n
addtimes_ [lst] a =
if a < 1
then [lst]
else addtimes_ [a:lst] (a-1)
main =
print $ addtimes 10
Though above code compiles and runs, it gives following runtime error:
testing: testing.hs:(3,1)-(6,37): Non-exhaustive patterns in function addtimes_
Where is the problem and how can it be solved?
See the following, with corrected syntax (and type signatures added, seriously these are essential for both code documentation and for better error messages):
addtimes :: (Num a, Ord a) => a -> [a]
addtimes n = addtimes_ [] n
addtimes_ :: (Num a, Ord a) => [a] -> a -> [a]
addtimes_ lst a =
if a < 1
then lst
else addtimes_ (a:lst) (a-1)
main :: IO ()
main =
print $ addtimes 10
As well as referring to [lst] (a singleton list containing the one element lst) instead of lst (which can refer to anything, which in the context of your function must be a list, but can be of any length), you had put [a:lst] (again a singleton list, this time containing a list) instead of (a:lst), a list made up of first element a appended to the front of lst. (The parentheses are not needed for any syntactic reason, but are usually needed in practice, as in the above code, because of operator precedence: addtimes_ a:list (a-1) would be parsed as (addtimes_ a):(list (a-1)), which definitely isn't what you mean.
Edit:
To achieve what you want, now I understand your goal reading your
addtimes :: Int -> [Int]
addtimes 0 = []
addtimes n = if n > 0
then addtimes_ 1 n
else error "Doesn't work with negatives"
addtimes_ :: Int -> Int -> [Int]
addtimes_ m n = if n > m
then m : (addtimes_ (m+1) n)
else [n]
main =
print $ addtimes (10)
That will create a list with the numbers adding 1 consecutively
[1,2,3,4,5,6,7,8,9,10]
Write the recursive function adjuster. Given a list of type
x, an int and an element of type x, either remove from the front of the
list until it is the same length as int, or append to the end of the list
until it is the same length as the value specified by the int.
expected:
adjuster [1..10] (-2) 2 -> *** Exception: Invalid Size
adjuster [1..10] 0 2 -> []
adjuster "apple" 10 ’b’ -> "applebbbbb"
adjuster "apple" 5 ’b’ -> "apple"
adjuster "apple" 2 ’b’ -> "le"
adjuster [] 3 (7,4) -> [(7,4),(7,4),(7,4)]
What i did:
adjuster (x:xs) count b
| count < 0 = error "Invalid Size"
| count == 0 = []
| count < length xs = adjuster xs (count-1) b
| otherwise = (adjuster xs (count-1) b):b
the error that I'm getting:
* Occurs check: cannot construct the infinite type: t ~ [t]
Expected type: [t]
Actual type: [[t]]
* In the expression: (adjuster xs (count - 1) b) : b
In an equation for `adjuster':
adjuster (x : xs) count b
| count < 0 = error "Invalid Size"
| count == 0 = []
| count < length xs = adjuster xs (count - 1) b
| otherwise = (adjuster xs (count - 1) b) : b
* Relevant bindings include
b :: [[t]] (bound at code01.hs:21:23)
adjuster :: [a] -> Int -> [[t]] -> [t] (bound at code01.hs:21:1)
I'm new in haskell.I'll really appreciate some help.
You are trying to construct a list within lists within lists and so on and so forth …
Why is this?
(:) :: a -> [a] -> [a]
The colon operator takes an element and a list of such elements as an argument and constructs a list from that (by prepending that element).
In your case if (adjuster ...) had type [a] then b must be of type [[a]], by line 4 which is the same as the end result, but line 3 says the type is [a] - which is different. This is what GHC tries to tell you.
How to fix it?
First of all, it is always a good advice to add a type signature to every top level function:
adjuster :: [a] -> Int -> a -> [a]
which should clean up your error-message and keep you honest, when implementing your function.
So how to fix this: - you could use b:adjuster xs (count-1) b but this would yield a result in the wrong order - so
choose a different operator: (++) and wrap the b inside a list.
| otherwise = (adjuster xs (count-1) b)++[b]
Now a few more hints:
turn on -Wall when you compile your file - this will show you that you missed the case of adjuster [] ...
using length is a relatively expensive operation - as it needs to traverse the full list to be calculated.
As an exercise - try to modify your function to not use length but only work with the base cases [] for list and 0 for count (here the function replicate might be helpful).
Here is another approach, without error handling
adjuster xs n v = tnr n $ (++) (replicate n v) $ tnr n xs
where tnr n r = take n $ reverse r
if you play with the signature, perhaps cleaner this way
adjuster n v = tnr . (++) (replicate n v) . tnr
where tnr = take n . reverse
I have the following code:
betaRest :: Int -> [Int] -> Int
betaRest n prevDigits | n == 0 = (length prevDigits)
| otherwise = (sum (map (betaRest (n - 1)) [0..9]))
betaFirst :: Int -> Int
betaFirst n | n == 0 = 0
| otherwise = (betaRest (n - 1) [1..9])
It gives me the following errors, and I don't know why.
1) No instance for (Enum [Int]) arising from the arithmetic sequence '0 .. 9'
2) No instance for (Num [Int]) arising from the literal '0'
Does Haskell think that things made with the ".." operator are enumerations? But why isn't there an error for the line that's 4 lines below (with "[1..9]") it then?
Edit: What I want the code to do is like this (procedurally):
int betaRest(int n, int[] prevDigits) {
if (n == 0) return prevDigits.length;
else {
sum = 0;
foreach prevDigit in prevDigits {
sum += betaRest(n - 1, [0..9]);
}
return sum;
}
}
int betaFirst(int n) {
if (n == 0) return 0;
else return betaRest(n - 1, [1..9]);
}
Thus, betaFirst(1) == 9, and betaFirst(2) == 90. Yes, somebody may want to suggest a formula for generating this, but I'm going to add a filter of some sort to [0..9], thus reducing the range.
You pass betaRest to map. Map is (a -> a) -> [a] -> [a] so for [Int] list you pass it it wants an Int -> Int function. But partially applied betaRest is [Int] -> Int.
As for [0..9] its type is (Enum t, Num t) => [t] and it's translated into enumFromTo 0 9 application. So compiler figured your error the other way around: if you define special Num and Enum instances for lists, so [0..9] becomes a list of lists of int, then your application will make sense.
But I think you want to use inits or tails function. Let us know what you want to achieve so we can help with solution.
A minimal fix to would be to add prevDigits as an argument to map and use a lambda abstraction to ignore unused prevDigit:
| otherwise = sum (map (\prevDigit -> betaRest (n - 1) [0..9]) prevDigits)
(sum (map (betaRest (n - 1)) [0..9]))
Let's reduce the number of parentheses to better be able to see what happens.
sum (map (betaRest (n - 1)) [0..9])
The argument of sum is
map (betaRest (n-1)) [0 .. 9]
Now, betaRest :: Int -> [Int] -> Int, hence the type of the partially applied function is
betaRest (n-1) :: [Int] -> Int
hence we can infer the type
map (betaRest (n-1)) :: [[Int]] -> [Int]
But the argument passed to map (betaRest (n-1)) is [0 .. 9], which has type
[0 .. 9] :: (Num a, Enum a) => [a]
The Num constraint comes from the use of an integer literal, and the Enum constraint from the use of the enumFromTo function (in its syntax-sugared form [low .. high]). Passing that as an argument to a function expecting an argument of type [[Int]] means the type variable a must be instantiated as [Int], and then the constraints need to be checked, i.e. the instances of [Int] for Num and Enum must be looked up. Neither of these exist, hence the error messages.
I'm not sure your procedural example is really what you want,
int betaRest(int n, int[] prevDigits) {
if (n == 0) return prevDigits.length;
else {
sum = 0;
foreach prevDigit in prevDigits {
sum += betaRest(n - 1, [0..9]);
}
return sum;
}
}
the foreach loop is much easier (and more efficiently) expressed as
sum = prevDigits.length * betaRest(n-1, [0 .. 9]);
so for the foreach to make sense, there should be a dependence on prevDigit in the loop body.
The translation to Haskell would be
betaRest n prevDigits
| n == 0 = length prevDigits
| otherwise = length prevDigits * betaRest (n-1) [0 .. 9]
-- or with the loop, with the small improvement that `betaRest (n-1) [0 .. 9]
-- is only computed once (if the Haskell implementation is sensible)
-- | otherwise = sum $ map (const $ betaRest (n-1) [0 .. 9]) prevDigits
But as stated above, I doubt that's really what you want.