Haskell allows to represent recurrent functions in a very concise way. For example, infinite list, that contains Fibonacci numbers can be defined as follows:
fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
I am dealing with 'probabilists' Hermite polynomials, which have the following recursion relation:
What would be the optimal way to construct the infinite list of n-th Hermite polynomials for given x?
We can write it as:
hermite :: (Enum n, Num n) => n -> [n]
hermite x = s
where s#(_:ts) = 1 : x : zipWith3 (\hn2 hn1 n1 -> x*hn1 - n1*hn2) s ts [1..]
where the first items 1 : x : ... are the first elements of the hermite (you can fill in other values).
For the next one, we zip the original values s (so that starts with H0), the tail ts of s (that starts with H1) and the index (that starts with 2, 3, ...) and perform an operation x*hn1 - x*hn2 (nh1 stands for Hn-1, and nh2 stands for Hn-2), and so we calculate the next element each time.
The first 11 values for x = 0.75 are:
Prelude> take 11 (hermite 0.75)
[1.0,0.75,-0.4375,-1.828125,-5.859375e-2,7.2685546875,5.744384765625,-39.30303955078125,-69.68797302246094,262.1583366394043,823.8105096817017]
So the first value is 1, the second x, the third one x*x-2, the fourth one x*x*x-2*x-3*x, and so on.
That being said, if I recall correctly, the recursion formula of the Hermite polynomials is:
Hn(x) = 2×x×Hn-1(x)-2×(n-1)Hn-2(x)
instead of the one quoted in the question.
In that case the formula is thus:
hermite :: (Enum n, Num n) => n -> [n]
hermite x = s
where s#(_:ts) = 1 : 2 * x : zipWith3 helper s ts [1..]
helper hn2 hn1 n1 = 2 * (x * hn1 - n1 * hn2)
Then the first 11 values are:
Prelude> take 11 (hermite 0.75)
[1.0,1.5,0.25,-5.625,-9.9375,30.09375,144.515625,-144.3515625,-2239.74609375,-1049.994140625,38740.4384765625]
Which is correct acording to this Wolfram article:
H0 = 1
H1 = 2*x
H2 = 4˙x2 - 2
H3 = 8˙x3 - 4˙x
H4 = 16˙x4 - 48˙x2 + 12
Which maps exactly on the values we obtained:
Prelude> let x = 0.75 in [1,2*x,4*x*x-2,8*x*x*x-4*x,16*x*x*x*x-48*x*x+12]
[1.0,1.5,0.25,0.375,-9.9375]
Related
I've been struggling with foldr for a while now. i want to convert a list of ints to a single tuple that contains the sum of list and number of ints. for example [1,2,3,4] -> (10,4)
the function i have below iterates through the list fine but only outputs the last element as the x val and 1 as the y val.
toTuple xs = let tuple = foldl (\a b -> ((sum1 + b),(len1 + 1))) (0.0,0.0) xs
in tuple
where sum1 = 0
len1 = 0
i originally had sum1 and len1 as functions that take in an single int as an input but that didnt' work either so i changed them to variables initailized to 0. however it seems like its setting sum and len to 0 at every element in the list. any suggestions to modify this? thanks!
It looks like you haven’t built an intuition for folds yet. You can think of a fold like foldl combine start input as starting with some start value, then combining that value with each element of the input using the combine function. The function accepts the current “state” and the next element of the list, and returns the updated state. So you are very close to a working solution:
toTuple xs = foldl (\ (sum, len) x -> (sum + x, len + 1)) (0, 0) xs
Stepping through an example input like [1, 2, 3, 4], the state (sum, len), usually called an “accumulator”, takes on the following values each time the folding function is called:
(0, 0)
(0+1, 0+1) = (1, 1)
(0+1+2, 0+1+1) = (3, 2)
(0+1+2+3, 0+1+1+1) = (6, 3)
(0+1+2+3+4, 0+1+1+1+1) = (10, 4)
At no point are we modifying any variables, just calculating the next value of the sum and the length by combining the current partial sum & length with each element of the list. For a left fold (foldl) that’s done from left to right; for a right fold (foldr) it’s from right to left, so the order of the parameters ((sum, len) and x) is reversed:
toTuple xs = foldr (\ x (sum, len) -> (sum + x, len + 1)) (0, 0) xs
However, for right folds, I find it easier to think of them as replacing all the : in a list with a function and replacing the [] with a value:
foldr f z [1, 2, 3, 4]
foldr f z (1 : (2 : (3 : (4 : []))))
1 `f` (2 `f` (3 `f` (4 `f` z)))
Well foldl has type foldl :: (a -> b -> a) -> a -> [b] -> a with a the type of the accumulator (here a 2-tuple), and b the type of elements in the list.
But in your lambda expression you write
\a b -> ((sum1 + b),(len1 + 1))
Note that here the variable b is an element of the list, and a is a tuple. But here you omit the accumulator. You always add sum1 to b, but since sum1, is a constant, that is rather useless. The same for len1, as a result, you will always obtain a tuple that contains the last element of the list as first item, and 1 as second item.
But based on your attempt, I think that you somehow aim to write "imperative" code in Haskell. Now in Haskell all variables are immutable, so setting len1 to 0 (in the where clause), will result in the fact that len1 is always 0, etc. We do not change the accumulator, in fact foldr is a recursive function that each time calls itself with parameters with different values, and at the end returns the parameter we call the "accumulator".
We can thus change the attempt to:
toTuple = (Fractional s, Fractional n) => [s] -> (s, n)
toTuple = foldl (\(cursum, curlen) b -> (cursum + b, curlen + 1)) (0.0,0.0)
So here we each time pattern match the accumulator with (cursum, curlen) (containing the "current" (thus far) sum and length), and each time we construct a new tuple that contains the "new" current sum (the sum of the old sum and b), and the "new" current length (the length incremented with one).
But it it still not very elegant: here the initial tuple has value (0.0, 0.0), but as a result, you tell Haskell that this is a 2-tuple where both elements are Fractionals. Although this will probably work given there are no rounding errors, why restrict this to Fractionals? If you have a list of Integers for example, we can sum these up without any rounding errors. By using (0, 0) as initial tuple, we make the tuple a 2-tuple where both elements have a type that belongs to the Num typeclass: so numbers. Note that the two do not per se have the same Num type, which is less restrictive.
So now we got:
toTuple = (Num s, Num n) => [s] -> (s, n)
toTuple = foldl (\(cursum, curlen) b -> (cursum + b, curlen + 1)) (0, 0)
I'm new to Haskell and I really need some help!
I have to write a program that includes a recursive function to produce a list of binomial coefficients for the power n=12 using the Pascal's triangle technique.
I have some ideas in my head but because I'm just getting started I have no idea how to implement this to haskell?!
Could someone please help me out??
first row: (a+b)^0 = 1
second row: (a+b)^1 = 1a+1b
third row: (a+b)^2 = 1a^2+2ab+1b^2
and so on...this is my main idea. But I cant even try this out because I have no idea how I put this in Haskell..getting errors all the time
Start by assigning an index to each element in the triangle:
| 0 1 2 3 4 5 6
--+--------------------------
0 | 1
1 | 1 1
2 | 1 2 1
3 | 1 3 3 1
4 | 1 4 6 4 1
5 | 1 5 10 10 5 1
6 | 1 6 15 20 15 6 1
Here I've simply put the triangle on its side so that we can number them. So here I'd say that the element at (6, 4) is 15, whereas (4, 6) doesn't exist. Now focus on writing a function
pascal :: Integer -> Integer -> Integer
pascal x y = ???
Such that you can generate this version of the triangle. You can start by writing
pascal x y
| x == 0 = 1
| x == y = 1
| x < y = error "Not a valid coordinate for Pascal's triangle."
| otherwise = pascal ? ? + pascal ? ?
Note that here, instead of figuring out which elements should be added together by diagonals, you can do it via rectangular coordinates. Here, you'll note that y is which row in the triangle you're on and x is the position of the element in that row. All you need to do is figure out what goes in place of the ?s.
Once you get that working, I've got a one-liner for this triangle that is more efficient and can generate the entire triangle all at once while still using recursion:
import Data.List (scanl1)
pascals :: [[Integer]]
pascals = repeat 1 : map (scanl1 (+)) pascals
Don't try turning this solution in to your professor, it's not what they're looking for and it would make it pretty obvious someone gave you this solution if you've only been doing Haskell for a week. However, it really shows how powerful Haskell can be for this sort of problem. I would show how to index pascals to get a given (n, k) value, but doing so would also give you too many hints for solving the naive recursion.
Since there's been some confusion, the reason why I gave this solution is to draw a parallel between it and the often shown lazy implementation for the Fibonacci sequence:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
Compared to
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
This definition generates an infinite list of all the Fibonacci numbers, and does so quite efficiently (from the point of view of the CPU, RAM is a different story). It encodes in its first 2 elements the base case, then a recursive expression that can calculate the rest. For the Fibonaccis, you need 2 values to start you off, but for Pascal's triangle, you only need one value, that value just happens to be an infinite list. There is an easy to see pattern going across the columns in the grid I posted above, the scanl1 (+) function just takes advantage of this pattern and allows us to generate it very easily, but this is generating the diagonals of the triangle rather than the rows. To get the rows, you can index this list, or you can do some fancy tricks with take, drop, and other such functions, but that's an exercise for another day.
Start out with the triangle itself:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
You should notice that to write down the next row, you must apply this rule: sum the previous rows' adjacent elements, using a 0 for the lonely edge elements. Visually:
0 1 0
\+/ \+/
0 1 1 0
\+/ \+/ \+/
0 1 2 1 0
\+/ \+/ \+/ \+/
1 3 3 1
...
Operationally, that looks like this:
For row 0:
[1] (it's a given; i.e. base case)
For row 1:
[0, 1] <- row 0 with a zero prepended ([0] ++ row 0)
+ +
[1, 0] <- row 0 with a zero appended (row 0 ++ [0])
= =
[1, 1] <- element-wise addition
For row 2:
[0, 1, 1]
+ + +
[1, 1, 0]
= = =
[1, 2, 1]
Generally, for row N:
element-wise addition of:
[0] ++ row(N-1)
row(N-1) ++ [0]
Remember that element-wise addition of lists in Haskell is zipWith (+).
Thus we arrive at the following Haskell definition:
pascal 0 = [1]
pascal n = zipWith (+) ([0] ++ pascal (n-1)) (pascal (n-1) ++ [0])
Or in a fashion similar to the famous "lazy fibs":
pascals = [1] : map (\xs -> zipWith (+) ([0] ++ xs) (xs ++ [0])) pascals
Another possible solution (more suitable for beginners in my opinion):
pascal :: Integer -> [Integer]
pascal 0 = [1]
pascal 1 = [1, 1]
pascal n = let p = pascal (n - 1)
in [1] ++ pascalStep p ++ [1]
pascalStep :: [Integer] -> [Integer]
pascalStep [] = []
pascalStep [_] = []
pascalStep (x:y:xs) = x + y : pascalStep (y : xs)
Using let to avoid more space usage.
pascal is calling recursively to find all previous rows, using them to get the next row, until getting to the desired row.
Output:
*Main> pascal 3
[1,3,3,1]
*Main> pascal 4
[1,4,6,4,1]
*Main> pascal 5
[1,5,10,10,5,1]
Start with the base case.
pascal 0 0 = 1
Then handle the edge cases
pascal n 0 = 1
pascal n r | n == r = 1
Now expand with the recursive step
pascal n r = pascal (n - 1) (r - 1) + pascal (n - 1) r
If you want the list for a specific row, write a wrapper
binom n = map (pascal n) [0..n]
Figuring out the types shouldn't be hard
pascal :: Integral a => a -> a -> a
binom :: Integral a => a -> [a]
I'm on my phone so please excuse the mistakes, but you can use Haskell's lazy evaluation in a really cool way here.
pascals :: [[Int]]
pascals = [1]:map (\r -> zipWith (+) (0:r) (r++[0])) pascals
Which you could make point free with a fork but it's rather esoteric.
pascals :: [[Int]]
pascals = [1]:map ((zipWith (+) -<) (0:) (++[0])) pascals
But I personally really like this code, and thinks it's worth being readable-
pascals :: [[Int]]
pascals = [1]:map next pascals
where next = (zipWith (+) -<) (0:) (++[0])
But combinators like that can get a bit confusing, no matter how much I like point free programming.
I have come up with the following tail-recursive fibonacci generator that works:
let {
fibo :: Integral x => [x]->x->x->x->[x]
fibo l x y 0 = l
fibo l x y n = fibo (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
}
Pardon me for the whole implementation put in one line because i am using the GHCi and haven't quite learnt how to put this in a file and run (i am yet to reach there). What i want to know is how this call:
fibo [0, 1] 0 1 5
can be improved. I do not want to pass the initial list with 0 and 1 and then pass 0 and 1 again with the limit. I believe that the implementation can be changed. What changes can be done?
Your algorithm is tail-recursive, but it looks like it has other drawbacks, namely 1) you are building the result list by appending to the end of it, and 2) it's not lazy.
For 1), note that when you append two lists a ++ b, you essentially have to reallocate a. In your case a is the growing list of fibonacci numbers and b are the next two terms. So each iteration reallocates the fibonacci numbers that have already been computed and adds on two more elements which will result in quadratic running time. It would be more efficient to prepend b to the front of a. You'll be producing the fibonacci numbers in reverse, but the running time will be linear. You can then reverse the list at the end if you want the sequence in ascending order.
Note that building the list in reverse order allows you to easily get at the last two terms of the sequence by using Code-Guru's pattern-matching idea.
For 2), note that you can't get the first element of the list until the entire computation has completed. Compare with the following lazy generation of the sequence:
fibs = 0 : (go 0 1)
where go a b = b : go b (a+b)
Even though it looks like the recursion never stops, fibs is only evaluated for as much as is needed. For example, fibs !! 3 only calls go a couple of times.
I'm not going to go to the algorithm itself, but here's some advice on how to structure your recursive functions.
First, here's how you would format your code in a separate file
fibo :: Integral x => [x]->x->x->x->[x]
fibo l x y 0 = l
fibo l x y n = fibo (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
If you save this as fibo.hs, then you can start GHCi with
ghci fibo.hs
to load the file at start. You can also load the file after starting GHCi with the command
:l fibo.hs
(assumming you start GHCi in the same directory where you saved fibo.hs)
Another nice feature is that now when you edit the file, you can reload all your changes by simply entering
:r
in the GHCi prompt.
Now, to get rid of the extra parameters, the usual pattern in Haskell is to refactor the recursive part to its own helper function and have the main function as an entry point that only takes the necessary parameters. For example,
fibo :: Integral x => x -> [x]
fibo n = fiboHelper [0,1] 0 1 n
fiboHelper :: Integral x => [x]->x->x->x->[x]
fiboHelper l x y 0 = l
fiboHelper l x y n = fiboHelper (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
Now you can call fibo simply with
> fibo 3
[0,1,1,2,3,5,8,13]
Also, a helper function like this that is not useful by itself is usually hidden inside the main function as an inner function using let or where.
fibo :: Integral x => x -> [x]
fibo n = fiboHelper [0,1] 0 1 n where
fiboHelper l x y 0 = l
fiboHelper l x y n = fiboHelper (l ++ [y+x] ++ [y+x+y]) (x+y) (y+x+y) (n-1)
An inner function like this is usually given a shorter name, because the context makes its purpose clear, so we could change the name to e.g. fibo'.
go is another commonly used name for a recursive helper function.
Just for the record: The "usual" definition for a list of Fibonacci numbers is:
fibo = 0 : scanl (+) 1 fibo
Does there exist a equation expander for Haskell?
Something like foldr.com: 1+(1+(1+(1+(…))))=∞
I am new to Haskell I am having trouble understanding why certain equations are more preferable than others. I think it would help if I could see the equations expanded.
For example I found foldr vs foldl difficult to understand at first until I saw them expanded.
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr k z xs = go xs
where
go [] = z
go (y:ys) = y `k` go ys
foldl :: (a -> b -> a) -> a -> [b] -> a
foldl f z0 xs0 = lgo z0 xs0
where
lgo z [] = z
lgo z (x:xs) = lgo (f z x) xs
From the definitions I can see that foldr expands like this:
foldr (+) 0 [1..1000000] -->
1 + (foldr (+) 0 [2..1000000]) -->
1 + (2 + (foldr (+) 0 [3..1000000])) -->
1 + (2 + (3 + (foldr (+) 0 [4..1000000]))) -->
1 + (2 + (3 + (4 + (foldr (+) 0 [5..1000000])))) -->
and foldl expands like this:
foldl (+) 0 [1..1000000] -->
foldl (+) (foldl (+) 0 [1]) [2..1000000]) -->
foldl (+) (foldl (+) (foldl (+) 0 [1])) [3..1000000]) -->
or from Haskell Wiki on foldr fold foldl':
let z1 = 0 + 1
in foldl (+) z1 [2..1000000] -->
let z1 = 0 + 1
z2 = z1 + 2
in foldl (+) z2 [3..1000000] -->
let z1 = 0 + 1
z2 = z1 + 2
z3 = z2 + 3
in foldl (+) z3 [4..1000000] -->
let z1 = 0 + 1
z2 = z1 + 2
z3 = z2 + 3
z4 = z3 + 4
in foldl (+) z4 [5..1000000] -->
However, I have trouble on larger equations understanding why things work the way they do in Haskell. For example the first sieve function uses 1000 filters while the second sieve function takes only 24 to find the 1001 prime.
primes = sieve [2..]
where
sieve (p:xs) = p : sieve [x | x <- xs, rem x p /= 0]
primes = 2: 3: sieve (tail primes) [5,7..]
where
sieve (p:ps) xs = h ++ sieve ps [x | x <- t, rem x p /= 0]
-- or: filter ((/=0).(`rem`p)) t
where (h,~(_:t)) = span (< p*p) xs
Haskell Wiki on Primes
I have spent a good while working out and expanding by hand. I have come to understand how it works. However, an automated tool to expand certain expressions would greatly improve my understanding of Haskell.
In addition I think it could also serve to help questions that seek to optimize Haskell code:
Optimizing Haskell Code
Help optimize my haskell code - Calculate the sum of all the primes below two million
Is there a tool to expand Haskell expressions?
David V. Thank you for those links. Repr is definitely worth adding to my tool box. I would like to add some additional libraries that I found useful.
HackageDB : Trace (As of December 12, 2010)
ghc-events library and program: Library and tool for parsing .eventlog files from GHC
hood library: Debugging by observing in place
hpc-strobe library: Hpc-generated strobes for a running Haskell program
hpc-tracer program: Tracer with AJAX interface
The Hook package seems to be what I am looking for. I will post more samples later today.
Hood
main = runO ex9
ex9 = print $ observe "foldl (+) 0 [1..4]" foldl (+) 0 [1..4]
outputs
10
-- foldl (+) 0 [1..4]
{ \ { \ 0 1 -> 1
, \ 1 2 -> 3
, \ 3 3 -> 6
, \ 6 4 -> 10
} 0 (1 : 2 : 3 : 4 : [])
-> 10
}
I was unaware of the Hackage library (as I am just getting into Haskell). It reminds me of Perl's CPAN. Thank you for providing those links. This is a great resource.
This is in no way a full reply to your question, but I found a conversation on Haskell-Cafe that have some replies :
http://www.haskell.org/pipermail/haskell-cafe/2010-June/078763.html
That thread links to this package :
http://hackage.haskell.org/package/repr that according to the page "allows you to render overloaded expressions to their textual representation"
The example supplied is :
*Repr> let rd = 1.5 + 2 + (3 + (-4) * (5 - pi / sqrt 6)) :: Repr Double
*Repr> show rd
"fromRational (3 % 2) + 2 + (3 + negate 4 * (5 - pi / sqrt 6))"
This is an answer to an unasked question, think of it as a long comment.
(Please downvote only then below 0, iff you think that it does not fit. I'll remove it then.)
As soon as you are a bit more experienced, you might not want to see the way things expand, anymore. You'll want to understand HOW things work, which then supersedes the question WHY it works; you won't gain much just by observing how it expands, anymore.
The way to analyse the code is much simpler than you might think: Just label every parameter/variable either as "evaluated" or "unevaluated" or "to-be-evaluated", depending on the progression of their causal connections.
Two examples:
1.) fibs
The list of all Fibonacci Numbers is
fibs :: (Num a) => [a]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
The first two elements are already evaluated; so, label the 3rd element (which has value 2) as to-be-evaluated and all remaining as unevaluated. The 3rd element will then be the (+)-combination of the first elements of fibs and tail fibs, which will be the 1st and 2nd element of fibs, which are already labelled as evaluated. This works with the n-th element to-be-evaluated and the (n-2)-nd and (n-1)-st already evaluated elements respectively.
You can visualize this in different ways, i.e.:
fibs!!(i+0)
+ fibs!!(i+1)
= fibs!!(i+2)
(fibs)
zipWith(+) (tail fibs)
= (drop 2 fibs)
1 : 1 : 2 : 3 ...
(1 :)1 : 2 : 3 : 5 ...
(1 : 1 :)2 : 3 : 5 : 8 ...
2.) Your example "sieve (p:ps) xs"
primes = 2: 3: sieve (tail primes) [5,7..]
where
sieve (p:ps) xs = h ++ sieve ps [x | x <- t, rem x p /= 0]
-- or: filter ((/=0).(`rem`p)) t
where (h,~(_:t)) = span (< p*p) xs
In "sieve (p:ps) xs",
p is evaluated,
ps is unevaluated, and
xs is an evaluated infinite partialy-sieved list (not containing p but containing p²), which you can guess reading the recursion and/or recognizing that the values of h need to be prime.
Sieve should return the list of primes after p, so at least the next prime is to-be-evaluated.
The next prime will be in the list h, which is the list of all (already sieved) numbers k where p < k < p²; h contains only primes because xs does neither contain p nor any number divisible by any prime below p.
t contains all numbers of xs above p². t should be evaluated lazy instead of as soon as possible, because there might not even be the need to evaluate all elements in h. (Only the first element of h is to-be-evaluated.)
The rest of the function definition is the recursion, where the next xs is t with all n*p sieved out.
In the case of foldr, an analysis will show that the "go" is only defined to speed up the runtime, not the readability. Here is an alternative definition, that is easier to analyse:
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr (.:) e (x:xs) = x .: (foldr (.:) e xs)
foldr (.:) e [] = e
I've described its functionality here (without analysis).
To train this type of analysing, you might want to read the sources of some standard libraries; i.e. scanl, scanr, unfoldr in the source of Data.List.
this is the question:
"Write a function that computes the
mean of a list, i.e. the sum of all
elements in the list divided by its
length. (You may need to use the
fromIntegral function to convert the
length of the list from an integer
into a floating point number.)"
first i tried this:
mean :: [Double] -> Double
mean [] = 0
mean (x:xs) = (x + mean xs) / (1 + mean xs)
but it give me strange results, for example, when i use it like that:
mean [2,4,6]
it give me the result: 1.41176
where it should be: 4
why?
i tried another thing:
mean :: [Double] -> Double
mean list = (summ list) / (count list)
where count [] = 0
count (x:xs) = 1 + count xs
summ [] = 0
summ (x:xs) = x + summ xs
but i have an error when i tried to load the file into GHC.
the error is:
parse error on input 'count'
Failed, modules loaded: none
again, what am i doing wrong?
at last, i tried this one (that succeeded):
mean :: [Double] -> Double
count [] = 0
count (x:xs) = 1 + count xs
summ [] = 0
summ (x:xs) = x + summ xs
mean list = summ list / count list
it's the same as the above one (with the 'where' keyword), but it succeed only here, and not in the above one.
why?
thanks a lot.
p.s.
i'm learning from the book -- Real World Haskell
and the exercise is from here -- (roll it down :-))
thanks to you all.
it's a strange thing.
the second example also work for me too when i copied it from here and tested it.
i don't know why it didn't work for me yesterday :-)
but i still don't understand why the first one doesn't work.
i think it should be like that
(2 + mean [4,6]) / (1 + mean [4,6])
(4 + mean [6 ]) / (1 + mean [ 6])
(6 + mean [ ]) / (1 + mean [ ])
so now it is like that
(6 + 0 ) / (1 + 0 ) -- last recursion
(4 + (6 + 0) ) / (1 + (1 + 0) )
(2 + (4 + (6 + 0))) / (1 + (1 + (1 + 0))
so now it should be: 12 / 3
isn't it?
what i don't understand?
thank you :-).
You get the wrong answers for your first attempt, because you use an incorrect formula. Garbage in, garbage out. (Other people have covered this.)
You are probably getting a parse error because some lines are using spaces and others are using tabs. Or you are using all tabs, but with a non-standard tab width.
No indentation is used or required here, so the spaces -v- tabs issue doesn't arise.
Your first attempt evaluates like so:
6 / 1
4 + 6 / 1 + 6
2 + (10/7) / 1 + (10/7)
which isn't what you wanted.
The second attempt is fine.
Correct:
import Data.List (foldl')
mean :: Fractional a => [a] -> a
mean = uncurry (/) . foldl' (\(s, n) x -> (s + x, n + 1)) (0, 0)
mean [2,4,6] = uncurry (/) $ foldl' (...) (0, 0) [2,4,6]
= uncurry (/) $ foldl' (...) (2, 1) [4,6]
= uncurry (/) $ foldl' (...) (6, 2) [6]
= uncurry (/) $ foldl' (...) (12, 3) []
= uncurry (/) (12, 3)
= 12 / 3
= 4
Incorrect:
mean [] = 0
mean (x:xs) = (x + mean xs) / (1 + mean xs)
mean [6] = mean (6 : [])
= (6 + mean []) / (1 + mean [])
= (6 + 0) / (1 + 0)
= 6
mean [4,6] = mean (4 : [6])
= (4 + mean [6]) / (1 + mean [6])
= (4 + 6) / (1 + 6)
= 10/7
mean [2,4,6] = mean (2 : [4,6])
= (2 + mean [4,6]) + (1 + mean [4,6])
= (2 + 10/7) / (1 + 10/7)
= 24/17
Say we define
naivemean l = sum l / fromIntegral (length l)
It has a couple of serious limitations. First, the definition does not cover lists of Int:
*Main> naivemean ([1] :: [Int])
<interactive>:1:0:
No instance for (Fractional Int)
arising from a use of `naivemean' at <interactive>:1:0-21
Possible fix: add an instance declaration for (Fractional Int)
In the expression: naivemean ([1] :: [Int])
In the definition of `it': it = naivemean ([1] :: [Int])
Second, it blows the stack for large lists:
*Main> naivemean [1..1000000]
*** Exception: stack overflow
Also, it makes two passes, one for sum and one for length, over the list when a single pass will do.
We can correct all three problems with
{-# LANGUAGE BangPatterns #-}
mean :: (Real a, Fractional b) => [a] -> b
mean = go (toRational 0) 0
where
go !s !l [] = fromRational s / fromIntegral l
go s l (x:xs) = go (s+.x) (l+1) xs
s +. x = s + toRational x
Bang patterns force strict evaluation of the marked parameters. Without the bangs, the code above will also blow the stack when given a long list, but for a different reason: lazy evaluation of l for example generates a long unevaluated chain of the form
0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + ...
In this case, lazy evaluation is creating more work in the form of allocating all the suspended computations than it would be to simply increment the counter on every iteration.
As a beginner, fromRational and toRational are probably confusing too. Consider the type of the division function:
*Main> :t (/)
(/) :: (Fractional a) => a -> a -> a
That means division is defined for any two values of the same type that is an instance of Fractional. Int is not one of those types:
*Main> (1::Int) / (2::Int)
<interactive>:1:0:
No instance for (Fractional Int)
arising from a use of `/' at <interactive>:1:0-18
Possible fix: add an instance declaration for (Fractional Int)
In the expression: (1 :: Int) / (2 :: Int)
In the definition of `it': it = (1 :: Int) / (2 :: Int)
One definition of mean ought to cover all of [Int], [Float], and [Double] but without the rational bits (and without the type annotation), the type inferred for mean is
*Main> :t mean
mean :: [Double] -> Double
because of the division by the length of the list.
It turns out that Int, Float, and Double are instances of the typeclass Real,and any Real may be converted to Rational
*Main> :t toRational
toRational :: (Real a) => a -> Rational
and Rational may be converted to Fractional:
*Main> :t fromRational
fromRational :: (Fractional a) => Rational -> a
Finally, for large lists, there's also a chance that we could overflow a machine double, but Rational gives us arbitrary precision.
If you have a background in languages such as C or Java that promote types automatically to handle these cases, you'll find this particular inflexibility of Haskell's type system to be confusing and frustrating. I'm afraid you just have to learn to deal with it.
Having done all that, we can now
*Main> mean ([1..1000000] :: [Int])
500000.5
or
*Main> mean ([1..1000000] :: [Double])
500000.5
Warning: untested code ahead. In your definition of mean, you need to accurately carry along both the running sum and the running length, and as others have pointed out, you're not doing that. Something like the following should work:
mean0 sum len [] = sum / len
mean0 sum len (x:xs) = mean0 (sum+x) (len+1) xs
This definition passes along two accumulators, one each for the running total and the running count, that are updated as you recurse along the list. When the function finally runs out of list to process (the base case) it just does the needed calculation.
To use mean0, you just write
mean0 0 0 [2, 4, 6]
As you can see, it's sort of annoying to provide the initial values for the accumulators, so it's common to provide a wrapper like
mean xs = mean0 0 0 xs
Now, you write mean [2, 4, 6] just like you wanted to.
Haskell: The most beautiful imperative language
import Control.Monad.ST
import Data.STRef
import Control.Monad
mean xs = s / l
where (s,l) = runST $ do{
acc <- newSTRef (0,0);
forM_ xs $ \x -> do{
modifySTRef acc $ \(a,b) -> (x+a,1+b)
};
readSTRef acc }
let mean x = sum (x) / fromIntegral(length(x))
mean [2.0, 4.0, 6.0]
Of course, this must be improved (empty list, does work for doubles...).