I want to take the user input of a list of numbers and find the average. However, after looking for examples I have not found any that seems to match what I am doing because I can have from 2 - 100 numbers in a list. Any help/advice is appreciated.
Below is my working code as is.
main = do
putStrLn "Enter how many numbers:"
listlen <- getLine
if ((read listlen) <= 100) -- read converts a string to a number
then do
putStrLn "Enter a String of numbers:"
--numberString <- getLine
numberString<- getLine
let ints = map read (words numberString) :: [Int]
putStrLn("The List: " ++(numberString))
putStrLn("The average: ")
putStrLn("Number of values greater than average: ")
else do
putStrLn " Error: listlen must be less than or = to 100"
main
Ok, this is homework, but homework can be really tough when you have to do it in Haskell. I'll try to explain step by step how you can do.
Good to know
First, Haskell is functional. You can find different defintions of "functional", but basically you can think of it as a property of the language: everything is constant (no side effect).
Second, you can start a REPL by typing ghci in a terminal:
jferard#jferard-Z170XP-SLI:~$ ghci
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Prelude> :set +m -- enable parsing of multiline commands
Prelude> -- type the expression you want to evaluate here
Recursion
How do you compute the sum of the elements of a list? In an imperative language, you will do something like that (Python like):
s = 0
for every x in xs:
s <- s + x
But s is not constant. It's updated on every iteration until we get the sum. Can we reformulate the algorithm to avoid this mutation? Fortunately yes. Here's the key idea:
sum [x] = x
sum [x1, ..., xn] = x1 + sum [x2, ..., xn]
With a little imagination, you can say that sum [] = 0. So we can write it in Haskell:
sum [] = 0
sum (x:xs) = x + sum xs
-- sum [1, 2, 3, 5] == 11
(x:xs) means: x (the head) followed by the list xs (the tail). If you have understood that, you know how we can avoid side effects in many situations: just call another function to do the rest of the job. (Note: if you know about the stack, you can imagine what happens under the hood.)
Now, how do you compute the length of a list? In a Python-like language, you'd do something like (forget len(..)):
l = 0
for every x in xs:
l <- l + 1
Again, with a recursive definition, you have:
length [] = 0
length (x:xs) = 1 + length xs
-- len [1, 2, 3, 5] == 4
Folds
Computing sum and length is so common that they are built-in functions in Haskell. But there is something more important: if you examine the two functions carefully, you'll notice this pattern:
f [] = <initial value>
f (x:xs) = g(f xs, x)
For sum, initial value is 0 and g(f xs, x) = x + f xs. For length, initial value is 0 and g(f xs, x) = 1 + f xs. This pattern is so common that Haskell has a built-in function (actually several built-in functions) for it: foldl. foldl takes a function, an initial value and a list and returns the function repeatedly applied to the previous result and the current element, until the list is consumed. You can think of the function as the the body of the loop:
sum xs = foldl (+) 0 xs
(Note on curryfication: 1. You will maybe learn some day that Haskell functions always take one argument, but that's not the point here. 2. You can remove xs on both sides: sum = foldl (+) 0)
Prelude> foldl (+) 0 [1,2,3,5]
11 -- (((0+1)+2)+3)+5
With scanl, you can in some way "debug" the foldl:
Prelude> scanl (+) 0 [1,2,3,5]
[0,1,3,6,11]
length is more tricky, since you don't have a built-in function g(f xs, x) = 1 + f xs. You can use a lambda function: \acc x -> 1 + acc where acc is the current value:
length xs = foldl (\acc x -> 1 + acc) 0 xs
Your question
Average
Let's try to write average with the built-in sum and length functions:
Prelude> average xs = sum xs / length xs
<interactive>:1:14: error:
• Could not deduce (Fractional Int) arising from a use of ‘/’
...
What does that mean? I won't get into details, but you have to know that Haskell is very strict with numbers. You can't divide two integers and expect a float result without a little work.
Prelude> :t (/)
(/) :: Fractional a => a -> a -> a
This means that / will take Fractionals. Thus, the work is: cast integers into Fractionals.
average xs = fromIntegral (sum xs) / fromIntegral (length xs)
-- average [1, 2, 3, 5] == 2.75
Number of values greater than average
Now, the number of values greater than the mean. In a Python-like langage, you'll write:
c = 0
for every x in xs:
if x > avg:
c <- c + 1
Let's try the recursive method:
gtAvg [] = 0
gtAvg (x:xs) = (if x>avg then 1) + sum xs -- WRONG
You see that there is something missing. In the imperative version, if x <= avg, we simply do nothing (and thus do not update the value). Here, we must return something:
gtAvg [] = 0
gtAvg (x:xs) = (if x>avg then 1 else 0) + gtAvg xs
But where does the avg value come from? We need to precompute it. Let's define a function that takes avg as an argument:
gtAvg' [] _ = 0
gtAvg' (x:xs) avg = (if fromIntegral x>avg then 1 else 0) + gtAvg' xs avg
-- gtAvg' [1, 2, 3, 5] (average [1, 2, 3, 5]) == 2
And then:
gtAvg xs = gtAvg' xs (average xs)
-- gtAvg [1, 2, 3, 5] == 2
Obviously, this is more simple with a foldl:
gtAvg xs = foldl (\acc x -> if fromIntegral x>average xs then acc+1 else acc) 0 xs
More (map, filter and list comprehension)
When we are on the basics of Haskell, you may need three more constructs.
Filter
First, a filter:
Prelude> filter (>2.75) [1, 2, 3, 5]
[3.0,5.0]
If you take the length of that list, you get the number of elements greater than the average:
gtAvg xs = length $ filter (\x -> fromIntegral x >average xs) xs
(Or with a composition of functions: length $ filter ((> average xs).fromIntegral) xs) Don't be disturbed by the $ sign: it means that the right side of the expression (filter...) is one block, like if it were in parenthesis.
Map
Second, map applies a function to every element of a list and returns the list of mapped elements. For instance, if you want to some squares of elements of a list:
Prelude> sum $ map (**2) [1, 2, 3, 5]
39.0
You can use it like that:
gtAvg xs = length $ filter (>average xs) $ map fromIntegral xs
It converts elements to Fractional, then it applies the filter.
List comprehension
Third, you can have filter and a map with a list comprehension:
gtAvg xs = length [x | x<-xs, fromIntegral x>average xs]
I left a lot of things aside and made probably approximations, but now you should have the basic knowledge to answer your question.
listlen :: [a] -> Int
listlen xs = go 0 xs -- 0 = initial value of accumulator
where go s [] = s -- return accumulator
go s (a:as) = go (s+1) as -- compute the next value of the accumulator
sumx :: [a] -> Int
sumx xs = go 0 xs
where go s [] = s
go s (a:as) = go ... as -- flll in the blank ... -- and recurse
lenAndSum :: [a] -> (Int,Int)
lenAndSum xs = go (0,0) xs -- (0,0) = initial values of both accumulators
where go (s1,s2) [] = (s1,s2) -- return both accumulators at the end
go (s1,s2) (a:as) = go ... as -- left as an exercise
main = do
putStrLn "Enter how many numbers:"
listlen <- getLine
if ((read listlen) <= 100) -- read converts a string to a number
then do
putStrLn "Enter a String of numbers:"
--numberString <- getLine
numberString<- getLine
let ints = map read (words numberString) :: [Int]
putStrLn("The List: " ++(numberString))
putStrLn("The average: ")
putStrLn("Number of values greater than average: ")
else do
putStrLn " Error: listlen must be less than or = to 100"
main`enter code here`
Related
I need to writea function titleRec :: [String] -> [String] which, given a list of
words, capitalises them as a title should be capitalised. The proper
capitalisation of a title (for our purposes) is as follows: The first word
should be capitalised. Any other word should be capitalised if it is
at least four letters long.
I came as far as,
capitalisedRec :: String -> String
capitalisedRec [] = []
capitalisedRec (x:xs) = toUpper x : lowered xs
where
lowered [] = []
lowered (x:xs) = toLower x : lowered xs
capitilized2 :: String -> String
capitilized2 xs = [toLower x | x <-xs]
titleRec :: [String] -> [String]
titleRec [] = []
titleRec (x:xs) = capitalisedRec x : adjust xs
where
adjust [] = []
adjust (y:ys) = [if (length y >= 4) then capitalisedRec y else capitilized2 y | y<- ys]
But when I run it on a list of strings, for example titleRec ["tHe", "bOSun", "ANd", "thE", "BriDGe"] it results in ["The","and","the","Bridge"], basically skips over the second word. I don't understand why.
Your code reads:
adjust (y:ys) =
[ if (length y >= 4)
then capitalisedRec y
else capitilized2 y
| y <- ys]
but the first y is not used later on, discarding it! The latter y is unrelated, and shadows the first one.
A minimal modification fix would be:
adjust (y:ys) =
[ if (length y2 >= 4)
then capitalisedRec y2
else capitilized2 y2
| y2 <- y:ys]
I would strongly recommend that you always keep warnings enabled using -Wall. Doing so, GHC would warn about y being unused (and about the shadowing as well).
I'm very new to Haskell and am trying to write a simple function that will take an array of integers as input, then return either the product of all the elements or the average, depending on whether the array is of odd or even length, respectively.
I understand how to set a base case for recursion, and how to set up boolean guards for different cases, but I don't understand how to do these in concert.
arrayFunc :: [Integer] -> Integer
arrayFunc [] = 1
arrayFunc array
| (length array) % 2 == 1 = arrayFunc (x:xs) = x * arrayFunc xs
| (length array) % 2 == 0 = ((arrayFunc (x:xs) = x + arrayFunc xs) - 1) `div` length xs
Currently I'm getting an error
"parse error on input '='
Perhaps you need a 'let' in a 'do' block?"
But I don't understand how I would use a let here.
The reason you have guards is because you are trying to determine the length of the list before you actually look at the values in the list.
Rather than make multiple passes (one to compute the length, another to compute the sum or product), just compute all of the values you might need, as you walk the list, and then at the end make the decision and return the appropriate value:
arrayFunc = go (0, 1, 0, True)
where go (s, p, len, parity) [] =
if parity then (if len /= 0 then s `div` len else 0)
else p
go (s, p, len, parity) (x:xs) =
go (s + x, p * x, len + 1, not parity) xs
There are various things you can do to reduce memory usage, and the recursion is just reimplementing a fold, but this gives you an idea of how to compute the answer in one pass.
Define an auxiliary inner function like that:
arrayFunc :: [Integer] -> Integer
arrayFunc [] = 1
arrayFunc array
| (length array) % 2 == 1 = go1 array
| (length array) % 2 == 0 = go2 array
where
go1 (x:xs) = x * go1 xs
go2 (x:xs) = ((x + go2 xs) - 1) `div` length xs
This deals only with the syntactical issues in your question. In particular, [Integer] is not an array -- it is a list of integers.
But of course the name of a variable doesn't influence a code's correctness.
Without focus on recursion this should be an acceptable solution:
arrayFunc :: (Integral a) => [a] -> a
arrayFunc ls
| n == 0 = 1
| even n = (sum ls) `div` (fromIntegral n)
| otherwise = product ls
where
n = length xs
For my homework assignment in ML I have to use the fold function and an anonymous function to turn a list of integers into the alternating sum. If the list is empty, the result is 0. This is what I have so far. I think what I have is correct, but my biggest problem is I cannot figure out how to write what I have as an anonymous function. Any help would be greatly appreciated.
fun foldl f y nil = y
| foldl f y (x::xr) =
foldl f(f(x,y))xr;
val sum = foldl (op -) ~6[1,2,3,4,5,6];
val sum = foldl (op -) ~4[1,2,3,4];
val sum = foldl (op -) ~2[1,2];
These are just some examples that I tested to see if what I had worked and I think all three are correct.
There are two cases: one when the list length is even and one when the list length is odd. If we have a list [a,b,c,d,e] then the alternating sum is a - b + c - d + e. You can re-write this as
e - (d - (c - (b - a)))
If the list has an even length, for example [a,b,c,d] then we can write its alternating sum as
- (d - (c - (b - a))).
So to address these two cases, we can have our accumulator for fold be a 3-tuple, where the first entry is the correct value if the list is odd, the second entry is the correct value if the list is even, and the third value tells us the number of elements we've looked at, which we can use to know at the end if the answer is the first or second entry.
So an anonymous function like
fn (x,y,n) => (x - #1 y, ~(x + #2 y), n + 1)
will work, and we can use it with foldl with a starting accumulator of (0,0,0), so
fun alternating_sum xs =
let
(v1, v2, n) = foldl (fn (x,y,n) => (x - #1 y, ~(x + #2 y), n + 1)) (0,0,0) xs
in
if n mod 2 = 0 then v2 else v1
end
I'm new to Haskell, started learning a couple of days ago and I have a question on a function I'm trying to make.
I want to make a function that verifies if x is a factor of n (ex: 375 has these factors: 1, 3, 5, 15, 25, 75, 125 and 375), then removes the 1 and then the number itself and finally verifies if the number of odd numbers in that list is equal to the number of even numbers!
I thought of making a functions like so to calculate the first part:
factor n = [x | x <- [1..n], n `mod`x == 0]
But if I put this on the prompt it will say Not in scope 'n'. The idea was to input a number like 375 so it would calculate the list. What I'm I doing wrong? I've seen functions being put in the prompt like this, in books.
Then to take the elements I spoke of I was thinking of doing tail and then init to the list. You think it's a good idea?
And finally I thought of making an if statement to verify the last part. For example, in Java, we'd make something like:
(x % 2 == 0)? even++ : odd++; // (I'm a beginner to Java as well)
and then if even = odd then it would say that all conditions were verified (we had a quantity of even numbers equal to the odd numbers)
But in Haskell, as variables are immutable, how would I do the something++ thing?
Thanks for any help you can give :)
This small function does everything that you are trying to achieve:
f n = length evenFactors == length oddFactors
where evenFactors = [x | x <- [2, 4..(n-1)], n `mod` x == 0]
oddFactors = [x | x <- [3, 5..(n-1)], n `mod` x == 0]
If the "command line" is ghci, then you need to
let factor n = [x | x <- [2..(n-1)], n `mod` x == 0]
In this particular case you don't need to range [1..n] only to drop 1 and n - range from 2 to (n-1) instead.
The you can simply use partition to split the list of divisors using a boolean predicate:
import Data.List
partition odd $ factor 10
In order to learn how to write a function like partition, study recursion.
For example:
partition p = foldr f ([],[]) where
f x ~(ys,ns) | p x = (x:ys,ns)
f x ~(ys,ns) = (ys, x:ns)
(Here we need to pattern-match the tuples lazily using "~", to ensure the pattern is not evaluated before the tuple on the right is constructed).
Simple counting can be achieved even simpler:
let y = factor 375
(length $ filter odd y) == (length y - (length $ filter odd y))
Create a file source.hs, then from ghci command line call :l source to load the functions defined in source.hs.
To solve your problem this may be a solution following your steps:
-- computers the factors of n, gets the tail (strips 1)
-- the filter functions removes n from the list
factor n = filter (/= n) (tail [x | x <- [1..n], n `mod` x == 0])
-- checks if the number of odd and even factors is equal
oe n = let factors = factor n in
length (filter odd factors) == length (filter even factors)
Calling oe 10 returns True, oe 15 returns False
(x % 2 == 0)? even++ : odd++;
We have at Data.List a partition :: (a -> Bool) -> [a] -> ([a], [a]) function
So we can divide odds like
> let (odds,evens) = partition odd [1..]
> take 10 odds
[1,3,5,7,9,11,13,15,17,19]
> take 10 evens
[2,4,6,8,10,12,14,16,18,20]
Here is a minimal fix for your factor attempt using comprehensions:
factor nn = [x | n <- [1..nn], x <- [1..n], n `mod`x == 0]
I have to derive the type of this function:
func x = map -1 x
And I've already found a way, using a tip to change it to a lambda expression:
func = \x -> (map) - (1 x)
If I express it like that, its fine and I get the same type as the original, but I'm not sure why its grouped like this. Could someone explain it?
For example, why isn't it like this:
func = \x -> (map - 1) x
or something similar.
I know it's a useless function etc. but I can't change the function, I just have to derive its type.
If you write this function in a file, eg:
test.hs has func x = map -1 x
and use :t func in the interpreter, it will reply:
func :: (Num (t -> (a -> b) -> [a] -> [b]),
Num ((a -> b) -> [a] -> [b])) =>
t -> (a -> b) -> [a] -> [b]
I now believe you meant to ask why
func x = map -1 x
has the type (Num (t -> (a -> b) -> [a] -> [b]), Num ((a -> b) -> [a] -> [b])) => t -> (a -> b) -> [a] -> [b], and how you can bracket the expression to make it have that type.
First, you have to recognise that the space is an operator in haskell, and has the highest precedence of all.
Let's use # instead of space, with highest precedence we can:
infixl 9 #
f # x = f x
We can replace and space without an operator with #:
func x = map - 1 # x
because the space between 1 and x was the only one without an operator (- is between map and 1).
Since # has higher precedence than -, we get
func x = map - (1 # x)
or equivalently
func x = map - (1 x)
Another example
func2 x = map (-1) x
> :t func2
func2 :: Num (a -> b) => [a] -> [b]
This translates as
func2' x = map # (-1) # x
but why isn't there a # between the - and the 1? In this case, - in front of a numeric literal like 1 means negate:
> (-1)
-1
> (negate 1)
-1
> (subtract 1)
<interactive>:73:1:
No instance for (Show (a0 -> a0))
arising from a use of `print'
Possible fix: add an instance declaration for (Show (a0 -> a0))
In a stmt of an interactive GHCi command: print it
So this function is trying to map the negative of 1 over a list. For that to work, it would need negative 1 to be a function, which is why it needs a numeric instance for functions (the Num (a->b) => at the start of the type).
but i'm not sure why its grouped like this. Could someone explain it? In example, why its not like that:
func = \x -> (map - 1) x
Precedence. The language definition specifies that the precedence of (prefix) function application is higher than that of any infix operator, so
map -1 x
is parsed as the application of the infix operator (-) to the two operands map and 1 x, like 3 + 4 * 5 is parsed 3 + (4 * 5) due to the higher precedence of (*) compared to that of (+).
Although the interpreter has assigned a type to the expression, it's not a sensible one. Let's see what the function should be
func x = map -1 x
looks like we want to bracket that like this
func x = map (-1) x
in the hope that it subtracts one from each element of a list, but unfortunately, the - is considered to be negation when it's in front of a numeric literal, so we need to bracket it to change it into the subtraction function:
func x = map ((-) 1) x
Now this function subtracts each number in the list from 1:
func [1,2,3]
=[(-) 1 1, (-) 1 2, (-) 1 3]
=[ 1-1, 1-2, 1-3]
=[ 0, -1, -2]
The type is
func :: Num a => [a] -> [a]
If you wanted to subtract one from each element of the list, rather than subtracting each element of the list from 1, you could use func x = map (subtract 1) x. As hammar points out, the subtract function exists exactly for the purpose of allowing this.
Your alternative
func = \x -> (map - 1) x
This can't work because (-) has type Num a => a -> a -> a, whereas map has type (a -> b) -> [a] -> [b]. You can't subtract one from a function, because a function isn't a numeric value.