This question already has answers here:
Haskell operator vs function precedence
(5 answers)
Closed 4 years ago.
I'm doing Project Euler with Haskell, and found something to learn when completing the very first problem. Here's my code:
isValid x = (mod x 3 == 0) || (mod x 5 == 0)
listValid :: Integer -> [Integer]
listValid n = [x | x <- [1..n-1], isValid x]
The function listValid will get all the positive integers less than n that are divisble by either 3 or 5. Easy enough.
*Main> listValid 10
[3,5,6,9]
Now I need to sum them. I figure the sum function is the right way to do this. What I don't understand is why the first two versions work, and then third doesn't.
*Main> sum (listValid 10)
23
*Main> sum $ listValid 10
23
*Main> sum listValid 10
<interactive>:4:5:
Couldn't match type ‘[Integer]’ with ‘a0 -> t’
Expected type: Integer -> a0 -> t
Actual type: Integer -> [Integer]
Relevant bindings include it :: t (bound at <interactive>:4:1)
In the first argument of ‘sum’, namely ‘listValid’
In the expression: sum listValid 10
Is this an order of operations problem, where I need to wrap in parentheses to assert which function should be applied first? And if so, what is the $ doing in the second version?
It's about associativity. Function application is left-associative, so sum listValid 10 is equivalent to (sum listValid) 10, not sum (listValid 10). And if you think about it, it has to be that way: If you define add x y = x+y, you wouldn't want add 1 2 to be equivalent to add (1 2).
So the issue here is that in sum listValid 10, it doesn't see listValid 10 as the argument to sum; it sees listValid as the argument to sum and then 10 as the argument to sum listValid.
$ resolves this issue because it's an infix operator and it's perfectly clear that sum is its left operand and listValid 10 is its right operand (keeping in mind that function application has higher precedence than any infix operator, so it can't be seen as (sum $ listValid) 10).
Function application f x is the highest-priority operation (and left-associative), so that
sum listValid 10
is equivalent to (sum listValid) 10.
The $ operator, on the other hand, has the lowest precedence possible (and is right-associative, although that isn't relevant here), so that
sum $ listValid 10
is implicitly the same as sum $ (listValid 10), not (sum $ listValid) 10. Thus, it is commonly used to eliminate parentheses.
When you write f $ x, you write in fact ($) f x, with ($) :: (a -> b) -> a -> b a function. This function is defined as:
($) :: forall r a (b :: TYPE r). (a -> b) -> a -> b
f $ x = f x
The above does not look very impressive. If you thus write f $ x, it is equivalent to f x, so then why write a $ anyway? Because this operator has precedence 0. It thus means that if you write:
f $ x+2
it is interpreted as:
($) f (x+2)
and thus:
f (x+2)
without the need to write brackets.
Going back to your question, if you write:
sum $ listValid 10
this is parsed as:
($) (sum) (listValid 10)
and thus functionally equivalent to:
sum (listValid 10)
If you however write:
sum listValid 10
Haskell interprets this as:
(sum listValid) 10
now the sum of a function with type Integer -> [Integer] does not make sense, sum :: Num a => [a] -> a should take a list of Numerical values, hence the error.
Function application is left-associative, so
f x y
is parsed as:
(f x) y
However, function application has higher precedence than any infix operator, so
f x $ g y
is parsed as:
(f x) $ (g y)
In particular, you have:
sum listValid 10 = (sum listValid) 10
sum $ listValid 10 = sum $ (listValid 10) = sum (listValid 10)
Related
I have to write a function sum that takes as first argument a value n. The second argument is a function f so that sum calculates the Gaussian sum.
In a second step, I have to implement thesum_gauss (int->int) using sum and a lambda expression.
This is my idea for the function sum:
let rec sum (n:int) (f:int->int) : int =
if n < 1 then 0
else sum (n-1) f + f n
And this is sum_gauss which throws an error:
let sum_gauss = sum ((i:int) -> fun (i:int) : int -> i)
The error is:
Line 1, characters 30-32:
Error: Syntax error: ')' expected
Line 1, characters 22-23:
This '(' might be unmatched
I don't understand why this error is raised because every left bracket is matched by a right bracket.
Rewriting with type inference cleaning things up:
let rec sum n f =
if n < 1 then 0
else sum (n-1) f + f n
If you wish to add all number from 1 to n. you need to pass the number and the function to sum_gauss as separate arguments.
let sum_gauss n = sum n (fun x -> x)
Of course, fun x -> x is really just Fun.id.
let sum_gauss n = sum n Fun.id
If you feel like being extra clever and you're already using the Fun module you can use Fun.flip to pass Fun.id as the second argument of sum and elide n from the definition entirely. The fact that sum is not polymorphic avoids weak typing issues with partial application.
let gauss_sum = Fun.(flip sum id)
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`
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'm reviewing an old exam in my Haskell programming course and I can't seem to wrap my head around this function (I think there is just too little information given).
The code given is
myId x = x
function n f
| n > 0 = f . function (n-1) f
| otherwise = myId
I know that if I for example call the function with the input 2 (*2), I will get a function as result. And if I call it with (-2) (*2) 1 I will get the result 1.
I just don't know how? Also I can't wrap my head around the typecast of the function.
I know that these two options are correct but I don't understand why (probably parentheses that confuse me at the moment).
function :: (Num a, Ord a) => a -> (a -> a) -> a -> a
function :: (Num a, Ord b) => a -> (b -> b) -> b -> b
Anyone that can clarify how I should "read" this function and how I should understand how the typecast works (been reading my Programming in Haskell literature and from Learn You a Haskell but been going in circle for a few days now).
function takes some number n and a function f :: a -> a, and composes that function with itself n times, returning another function of type a -> a. When the returned function is applied to a value of type a, the result is essentially the same as executing f in a loop n times, using the output of each previous step as the input for the next.
Perhaps it is easier to see the similarity if the final parameter is made explicit:
function :: (Ord a, Num a) -> a -> (b -> b) -> b -> b
function n f x
| n > 0 = f (function (n-1) f x)
| otherwise = x
This is functionally equivalent to your point-free function.
In Haskell, a function f :: a -> b -> c can be interpreted either as "a function that takes an a and a b and returns a c" or "a function that takes an a and returns a function from b to c". When you apply a function to one or more inputs, think of each input as eliminating one of the function's arguments. In this instance, function 10 returns a new function with type (a -> a) -> a -> a, and function 2 (*2) returns a function with type Num a => a -> a.
When you think of it this way, it should hopefully be clear why function (-2) (*2) 1 returns a number while function 2 (*2) returns a function. There is no type casting going on; when you are applying the three argument function to two inputs, you get another function back instead of a value, since you didn't provide the final input needed to compute that value.