I'm very new to Haskell. I've been trying to implement n_choose_r but for some reason my factorial function is returning strange values.
Main.hs
factorial 0 = 1
factorial n = n * factorial (n-1)
subsets k list = factorial n where
n = length list
some different cases
> subsets 3 [1..4]
24 // correct value
> factorial 60
8320987112741390144276341183223364380754172606361245952449277696409600000000000000
> subsets 3 [1..60]
-8718968878589280256 // wrong value
> subsets 3 [1..100]
0 // wrong value
It seems the numbers get wonkier the longer the list. Can anyone explain?
Your factorial function is polymorphic: it has type (Eq p, Num p) => p -> p. When you just call it like factorial 60, p gets instantiated as Integer (this choice is called "type defaulting"), which is arbitrary-precision and has no upper bound. However, length is not polymorphic in its output: it always returns an Int. Haskell won't automatically convert between numeric types for you, so when you call factorial with the result of length, it uses Int too, which does have an upper bound, which in your case appears to be 9223372036854775807 (which you can verify by doing maxBound :: Int). To work around this problem, you can either convert from Int to Integer yourself:
subsets k list = factorial (toInteger n) where
n = length list
or use genericLength, which is the same as length except for being polymorphic in its output type:
import Data.List
subsets k list = factorial n where
n = genericLength list
Note that if you use the latter option, you need to be careful not to do anything else that would force use of Int instead of defaulting to Integer.
Related
I am new to Haskell Programming. I tried to write a Haskell function to get the factorial of any given number by recursion. But it gets stack overflow exception.
factor x = x * (factor x-1)
You are getting the error since your recursion doesn't have a base case. You need a way for the program to stop once a certain condition is met.
There are many ways of doing the factorial calculation - recursion, product, or folds.
factorial n = product [1..n] -- product algorithm
import Data.List
factorial n = foldl' (*) 1 [1..n] -- fold algorithm
In the case of recursion, we always have two things:
The base case
How to get from one case to another
Considering some factorials:
1! = 1
2! = 2 x 1 = 2 x 1!
3! = 3 x 2 x 1 = 3 x 2!
4! = 4 x 3 x 2 x 1 = 4 x 3!
The base case, the final case, is 1!, or 1. The way of getting from n! to (n-1)! is to multiply n by (n-1)!
When we set out the factorial calculation, we have to do the base case first, otherwise Haskell will pattern match on the general case and never get to the base case. Also, it is a good practice to explicitly specify the types, in this case Integer (arbitrary sized integer) to Integer (arbitrary sized integer).
factor :: Integer -> Integer
factor 1 = 1
factor n = n * factor (n-1)
My factorial function seems to work for numbers between 1 and 6, but not for numbers much bigger than 6, for example starting with 21! the results are negative.
I cannot figure out why. Here's my function:
factorial :: Int -> Int
factorial 0 = 1
factorial 1 = 1
factorial num = num * factorial( num - 1)
And here's my binomial coefficient function that calls my factorial function (maybe the problem comes from this one ?):
binomialCoef :: Int -> Int -> Int
binomialCoef n 1 = n
binomialCoef n k = factorial n `div`
((factorial k) * factorial (n - k))
(…) realized my factorial function returns negative numbers starting at 21!, and I can't figure out why.
Because an Int has a fixed number of bits. An Int should at least represent all numbers between -2-29 and 229-1, and on a 64-bit system, typically it will represent numbers between -2-63 and 263-1, but regardless what bounds it represents, it will eventually run out of bits to represent such number.
You can work with Integer to represent arbitrary large numbers:
factorial :: Integer -> Integer
factorial 0 = 1
factorial 1 = 1
factorial num = num * factorial (num-1)
For example:
Prelude> factorial 21
51090942171709440000
Prelude> factorial 22
1124000727777607680000
The binomial coefficient is where ln(gamma) really shines:
Bi(n, k) = n!/(k!*(n-k)!)
Taking the natural log of both sides:
ln(Bi(n, k)) = ln(n!) - ln(k!) - ln((n-k)!)
But
gamma(n) = (n-1)!
Or
gamma(n+1) = n!
Substituting
ln(Bi(n, k)) = lngamma(n+1) - lngamma(k+1) -lngamma(n-k+1)
Taking the exponential of both sides gives the final result:
Bi(n, k) = exp(lngamma(n+1) - lngamma(k+1) - lngamma(n-k+1))
There's a Haskell implementation. I haven't looked at it, but it should return a Double instead of an Integer. You won't have overflow problems because of that fact. It'll also be better behaved because you will be subtracting logarithms instead of dividing a large numerator by a large product in the denominator.
Of course best way to avoid integer overflow and wrap-around while calculating a big factorial is not to calculate the factorial in the first place. Instead, since
factorial n = product [1..n]
keeping [1..n] as the representation of the factorial of n is as good -- or even much better -- as calculating the actual number. Postponing an action until absolutely unavoidable we get to pre-optimize it before post-calculating:
bincoef :: Int -> Int -> Int
bincoef n k = factorial n `div`
((factorial k) * factorial (n - k))
= product [1 .. n] `div`
(product [1 .. k] * product [1 .. n-k])
= product [n-k+1 .. n] `div`
product [1 .. k]
= foldl' g 1 $ zip [n, n-1 .. n-k+1] [1 .. k]
where g !acc (a,b) = (acc * a) `div` b
So now,
> mapM_ (\n -> print $ map (bincoef n) [5,10..n]) [20,30..60]
[15504,184756,15504,1]
[142506,30045015,155117520,30045015,142506,1]
[658008,847660528,40225345056,137846528820,40225345056,847660528,658008,1]
[2118760,10272278170,2250829575120,47129212243960,126410606437752,47129212243960,
2250829575120,10272278170,2118760,1]
[5461512,75394027566,53194089192720,4191844505805495,51915437974328292,1182645815
64861424,51915437974328292,4191844505805495,53194089192720,75394027566,5461512,1]
> head . filter (not . snd) $ map (\n -> (n, all (> 0) $ map (bincoef n) [1..n])) [1..]
(62,False)
the Int wrap-around error makes its first appearance at n=62. But it's still working at n=60, and we can see there are more than 16 digits in those numbers, so no Double-based calculation has a hope of working correctly, there.
To get into yet higher ranges still with the Int-based operations only, the next logical step is keeping the lists of integers as originally proposed, or better yet as their prime factorizations which are easy to multiply and divide; but at that point we'd be getting pretty close to re-implementing the bignum arithmetic ourselves, so might as well just use the simple Integer-based code,
bc :: Integer -> Integer -> Integer
bc n k = product [n-k+1 .. n] `div` product [1 .. k]
which "just works".
> bc 600 199
124988418115780688528958442419612410733294315465732363826979722360319899409241320138
666379143574138790334901309769571503484430553926248548697640619977793300443439200
I want to create a function which takes an n elements long list and returns sum of all elements multiplied by 3. The way I do it is here:
times3::Int->Integer
times3 x = sum [map (3*) [1..x]]
This code however results in the following error:
Couldn't match expected type `Integer' with actual type `[Int]'
Do you have any idea why is this happening?
[map (3*) [1..x]] is a list of length one, since [ some expression here ] is always a singleton list. In your code it's the list-of-lists [[3,6,...,3*x]] of type [[Int]] as the compiler reported.
Your type signature claims the result is Integer, and to obtain that, we would need to start with list of type [Integer]. The compiler checks the type equality [[Int]] ~ [Integer] and complains that [Int] is not Integer, hence the type error.
Instead, (map (3*) [1..x]) is a list of length x, namely [3,6,...,3*x], which is of type [Int]. This is the list I think you intended to use.
Since this list is not a [Integer], you either have to perform a conversion using fromIntegral or, more simply, to change your type signature in the function.
Another alternative would be to make the argument x an Integer.
#chi's answer explains what the problem is with the current implementation. The only thing I want to add is that the sum of *3, 6, 9, …, 3×n; can be determined without enumerating over a list. Indeed the sum:
n n
--- ---
\ \
/ 3 i = 3 / i
--- ---
i=1 i=1
the sum if 1, 2, …, n can be calculated with n×(n+1)/2, so we can calculate the sum with:
times3 :: Int -> Integer
times3 n = 3 * div (n * (ni+1)) 2
where ni = fromIntegral n
or without converting an Int to Integer and for any Integral type:
times3 :: Integral i => i -> i
times3 n = 3 * div (n * (n+1)) 2
With the following function:
factorial :: Int -> Int
factorial n = product [1..n]
The correct value is returned with parameters less than 21. For example:
factorial 20 returns 2432902008176640000, but factorial 21 returns -4249290049419214848 which isn't correct even if the value wasn't negative.
I know that with these size numbers Integer should have been utilized, but where specifically is the error occurring here and why?
Int in Haskell is a fixed-precision representation of the integers with a finite range. As is the case with most fixed-precision integer representations, an arithmetic operation that would create an integer that is too large or small to be represented (which is called an integer overflow, as mentioned by Mephy) will have its result wrapped by truncating it to its least significant bits. For example:
λ> maxBound + 1 :: Int
-9223372036854775808
λ> (maxBound + 1 :: Int) == minBound
True
I'm new to Haskell. It's very nice so far, but I'm running into copy-pasting for my QuickCheck properties, and I'd like to fix that.
Here's a made-up example:
prop_Myfunc :: [Int] -> (Int,Int) -> Bool
prop_Myfunc ints (i,j) = ints !! i == ints !! j
This won't work because QuickCheck generates negative numbers, so I get
*** Failed! (after 2 tests and 2 shrinks):
Exception:
Prelude.(!!): negative index
I've tried to google for solutions to this, and I've found e.g. NonNegative and ==>, but I don't understand how they work.
How can I restrict the above example so that i and j are never negative? And also, so that neither is too high? That is: 0 <= i,j < length ints
First, see this SO answer for an example of how to write a custom Gen ... function and how to use the forAll combinator.
And here is how to write a generator for a non-empty list and two valid non-negative indices into the list:
import Test.QuickCheck
genArgs :: Gen ( [Int], Int, Int )
genArgs = do
x <- arbitrary
xs <- arbitrary
let n = length xs
i <- choose (0,n)
j <- choose (0,n)
return ( (x:xs), i, j) -- return a non-empty list
test = quickCheck $ forAll genArgs $ \(xs,i,j) -> prop_myfunc xs (i,j)
Constraining wrappers (from Test.QuickCheck.Modifiers, if they aren't reexported implicitly) can be used in this way:
prop_Myfunc :: [Int] -> (NonNegative Int, NonNegative Int) -> Bool
prop_Myfunc ints (NonNegative i, NonNegative j) = ints !! i == ints !! j
You can treat SomeWrapper a as a with modified distribution. For example, NonNegative a ensures that a >= 0. After the wrapper was generated, the value can be get with pattern-matching or explicit accessor (getNonNegative in this case).
As for constraining the top margin of your indices, I think it's not possible with wrappers (it's impossible in the Haskkell type system to parameterise a type with the value, the list length in this case). However, with the ==> operator you can add an arbitrary boolean constraint for your test:
prop_Myfunc ints (NonNegative i, NonNegative j) = i < l && j < l ==> ints !! i == ints !! j where
l = length ints
It works in other way: when the condition isn't true, it simply discards the current test case. But be careful: if there are too many thrown cases (the condition is too restrictive), the test becomes much less useful. A „lossless“ behaviour can be often achieved with shrinking test data, but it's a whole other topic.
I was in a similar situation as you and I finally found how to use ==> here: http://www.cse.chalmers.se/~rjmh/QuickCheck/manual.html, in the "Conditional Properties" section.
With your example, you'd have to replace Bool with Property and insert the requirements about your variables before the property test, as follows:
prop_Myfunc :: [Int] -> (Int,Int) -> Property
prop_Myfunc ints (i,j) = (i >= 0 && j >= 0) ==> ints !! i == ints !! j
(I haven't tested on this particular example, but it worked for me on a similar case.)
Note the type of ==>: (==>) :: Testable prop => Bool -> prop -> Property.