I tried to implement logarithm algorithm, but it seems to be in a loop
loga_b :: Int -> Int -> Int
loga_b a b
| b == 1 = 0
| b == a = 1
| otherwise = 1 + loga_b (b `div` a) b
You switched the parameters in the last case - try this:
loga_b :: Int -> Int -> Int
loga_b a b
| b == 1 = 0
| b == a = 1
| otherwise = 1 + loga_b a (b `div` a)
examples:
λ> loga_b 2 8
3
λ> loga_b 2 17
4
remark
you don't really need the second case:
loga_b :: Int -> Int -> Int
loga_b a b
| b == 1 = 0
| otherwise = 1 + loga_b a (b `div` a)
if b == a then the last case will evaluate to the same 1:
1 + loga_b a (a `div` a)
= 1 + loga_b a 1
= 1 + 0
= 1
making it total
as Sassa mentioned this is a partial function right now and I'm not sure how you want this fixed correctly, but I think this should do ok:
loga_b :: Int -> Int -> Int
loga_b a b
| b < 0 || a < 0 = signum a * signum b * loga_b (abs a) (abs b)
| b < a = 0
| b >= a = 1 + loga_b a (b `div` a)
Note this will note give sensible behaviour for negative numbers I know - but I'm sure if the OP really needs it he can think about all the cases himself ;)
Related
I am using Euclid's algorithm for computing GCD(M,N), the greatest common divisor of two integers M and N.
Though this code works well, I felt it's bit cumbersome to wrap it with max, min, and abs for both variables (a, b).
Can anyone suggest a better way to make the code less verbose?
I found the built-in gcd type was defined as gcd :: Integer a => a -> a -> a, but I cannot simply use it. What do I need to change in order to reuse the type definition?
gcd2 :: Int -> Int -> Int
gcd2 a b =
let x = max (abs a) (abs b)
y = min (abs a) (abs b)
in if (y == 0) || (x == y && x > 0)
then x
else gcd2 y (x-y)
Well, inspired by chi, I changed the code as below.
gcd3 :: Int -> Int -> Int
gcd3 a b | a < 0 = gcd3 (-a) b
| b < 0 = gcd3 a (-b)
| b > a = gcd3 b a
| b == a || b == 0 = a
| otherwise = gcd3 b (a-b)
This is the best I can do. :)
As suggested by chi in his answer, to avoid using abs in each recursive step I’d define a GCD local function where you pass the absolute value of the arguments. This way the implementation is pretty straightforward:
gcd :: Int -> Int -> Int
gcd a b = gcd' (abs a) (abs b)
where gcd' a 0 = a
gcd' a b = gcd' b (a `mod` b)
You can look at how it is implemented in base:
gcd :: (Integral a) => a -> a -> a
gcd x y = gcd' (abs x) (abs y)
where gcd' a 0 = a
gcd' a b = gcd' b (a `rem` b)
I want to make this Function:
calling customPower 2 2
would give back 2^2 + 2^1 + 1
calling customPower 3 3
would give back 3^3 + 3^2 + 3^1 + 1
Here is my code:
customPower :: Int -> Int -> Int
customPower x y
| y == 0 = 1
| y > 0 = (x^(y)) + (customPower x y-1)
It gives me stack overflow exception and I can't find where is the error. Everything seems fine.
The operators have lower precedence than function calls, this means that your recursive call:
... + (customPower x y-1)
is interpreted as:
... + ((customPower x y)-1)
so you keep calling with the same parameters, therefore the recursion can never end.
We can fix this by adding brackets for y-1:
customPower :: Int -> Int -> Int
customPower x y
| y > 0 = x^y + customPower x (y-1)
| otherwise = 1
With this modifications, we do not get stuck in an infinite loop:
Prelude> customPower 5 3
156
We can rewrite the above by making use of sum :: Num a => [a] -> a and map :: (a -> b) -> [a] -> [b] to implement this with a one-liner:
customPower :: (Num a, Integral b) => a -> b -> a
customPower x y = sum (map (x^) [0..y])
or we can use iterate :: (a -> a) -> a -> [a]:
customPower :: (Num a, Integral b) => a -> b -> a
customPower x y = sum (take (y+1) (iterate (x*) 1))
Due to Haskell's laziness, the above attempts will likely still result in a call stack that scales linear with the value of y: the functions are, like #dfeuer says, not tail recursive functions, we can however work with an accumulator here:
customPower :: Int -> Int -> Int
customPower x = go 1
where go a y | y > 1 = a
| otherwise = seq a (go (a+x^y) (y-1))
since the above sum is equal to a simple formula, we can even calculate the value in O(y log x):
y
.———— y+1
╲ i x - 1
╱ x = ————————
*———— x - 1
i=0
So we can calculate the value with:
customPower :: (Integral a, Integral b) => a -> b -> a
customPower x y = div (x^(y+1) - 1) (x - 1)
This will usually work faster, although in a rare case where the result times x -1 is larger than the maximum representable number of the type a, this will result in overflow and will return the wrong number.
I'm new to Haskell and i don't understand why my guard won't accept it. here's my code. The guard should fire in case b is a divider of a.
gCF :: Integer -> Integer -> Integer;
gCF n p
| (p <= 0 || n <= 0) = error "Input should be positive"
| (p > n) = f p n
| otherwise = f n p
where
f :: Integer -> Integer -> Integer;
f a b
| (fromInteger (a `div` b) / 1 == a / b) = b
| otherwise = f a (b - 1)
Here's the error shown.
testscript.hs:168:28: error:
• No instance for (Fractional Integer) arising from a use of ‘/’
• In the first argument of ‘(==)’, namely
‘fromInteger (a `div` b) / 1’
In the expression: (fromInteger (a `div` b) / 1 == a / b)
In a stmt of a pattern guard for
an equation for ‘f’:
(fromInteger (a `div` b) / 1 == a / b)
|
168 | | (fromInteger (a `div` b) / 1 == a / b) = b | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
I think you make it the function more complex that necessary. Converting numbers between the Integer and Floating world can be dangerous, since it introduces rounding problems.
If I understand it correctly, you want to check if a is dividable by b. You can check this by verifying that mod a b == 0, and we are still in the integer worlds. So we can rewrite the program to:
gCF :: Integer -> Integer -> Integer
gCF n p | p <= 0 || n <= 0 = error "Input should be positive"
| p > n = f p n
| otherwise = f n p
where f a b | mod a b == 0 = b
| otherwise = f a (b-1)
Since a does not change in the recursive calls, we can factor that out:
gCF :: Integer -> Integer -> Integer
gCF n p | p <= 0 || n <= 0 = error "Input should be positive"
| otherwise = f (min p n)
where a = max p n
f b | mod a b == 0 = b
| otherwise = f (b-1)
We can also generalize the signature to let it work with any Integral type:
gCF :: Integral i => i -> i -> i
gCF n p | p <= 0 || n <= 0 = error "Input should be positive"
| otherwise = f (min p n)
where a = max p n
f b | mod a b == 0 = b
| otherwise = f (b-1)
i found a solution!
gCF :: Integer -> Integer -> Integer;
gCF n p
| (p <= 0 || n <= 0) = error "Input should be positive"
| (p > n) = floor (f (fromInteger p) (fromInteger n) (fromInteger n))
| otherwise = floor (f (fromInteger n) (fromInteger p) (fromInteger p))
where
f :: Float -> Float -> Float -> Float;
f a b c
| (fromInteger (floor (a / c)) == a / c) && (fromInteger (floor (b / c)) == b / c) = c
| otherwise = f a b (c - 1)
With the program below,
f 0 0 0 1 = 0
f 0 0 1 0 = f 0 0 0 1 + 1
f 0 1 0 0 = f 0 0 1 1 + 1
f 1 0 0 0 = f 0 1 1 1 + 1
f a b c d = (p + q + r + s) / (a + b + c + d)
where
p
| a > 0 = a * f (a - 1) (b + 1) (c + 1) (d + 1)
| otherwise = 0
q
| b > 0 = b * f a (b - 1) (c + 1) (d + 1)
| otherwise = 0
r
| c > 0 = c * f a b (c - 1) (d + 1)
| otherwise = 0
s
| d > 0 = d * f a b c (d - 1)
| otherwise = 0
main = print (f 1 1 1 1)
I thought it can be simplified as,
f 0 0 0 1 = 0
f 0 0 1 0 = f 0 0 0 1 + 1
f 0 1 0 0 = f 0 0 1 1 + 1
f 1 0 0 0 = f 0 1 1 1 + 1
f a b c d = (p + q + r + s) / (a + b + c + d)
where
p = a * f (a - 1) (b + 1) (c + 1) (d + 1)
q = b * f a (b - 1) (c + 1) (d + 1)
r = c * f a b (c - 1) (d + 1)
s = d * f a b c (d - 1)
main = print (f 1 1 1 1)
because besides both being mathematically sound, I thought that with lazy evaluation, the compiler or interpreter should be able to decide that multiplying anything to 0 is needless. But well, the program did go into infinite loop. Why so?
Built-in multiplication is strict in both arguments -- that is, it evaluates both arguments -- regardless of whether one of them is zero, which is what is causing your program to loop. You could define your own multiplication operator which lazily eliminates one or the other of the arguments:
0 .* y = 0
x .* y = x * y
or the other way around. It takes a bit more to define an operator which eliminates zero on both sides, but it can be done with the unamb package:
x .* y = unambs [ assuming (x == 0) 0
, assuming (y == 0) 0
, x * y
]
Though, as far as I know, this does not yet have a sufficiently reliable implementation :-/.
As well as defining your own multiplication operator as #luqui suggests, you can define your own type whose built-in multiplication short-circuits:
newtype SCZero a = SCZero a
deriving Eq
instance Show a => Show (SCZero a) where
show (SCZero x) = show x
instance (Eq a, Num a) => Num (SCZero a) where
SCZero x + SCZero y = SCZero (x + y)
SCZero 0 * SCZero y = SCZero 0
SCZero x * SCZero y = SCZero (x * y)
abs (SCZero x) = SCZero (abs x)
signum (SCZero x) = SCZero (signum x)
fromInteger x = SCZero (fromInteger x)
negate (SCZero x) = SCZero (negate x)
instance (Eq a, Fractional a) => Fractional (SCZero a) where
fromRational x = SCZero (fromRational x)
SCZero 0 / SCZero y = SCZero 0
SCZero x / SCZero y = SCZero (x / y)
You can then use your existing code directly, by just specifying the result type to be a SCZero:
*Main> print (f 1 1 1 1 :: SCZero Double)
0.464398781601087
I tried all possible type declarations but I can't make this code even compile. The trick is in handling types for division. I tried Num a, Fractional a, Float a etc.
cube x = x * x * x
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral f a b n = (h / 3) * (sum' term 0 succ n) where
h = (b - a) / n
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k
| odd k = 4 * y k
| even k = 2 * y k
main = do
print $ integral cube 0 1 100 -- 0.25
print $ (\x -> 3 * x * x) 1 3 100 -- 26
I isolated problem by deleting (/) function. This code compiles without any type declaration at all:
cube x = x * x * x
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral f a b n = (sum' term 0 succ n) where
h = (b - a)
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k
| odd k = 4 * y k
| even k = 2 * y k
main = do
print $ integral cube 0 1 100
Another question is how to debug cases like this? Haskell's error messages doesn't help much, it's kind of hard to understand something like The type variable a0 is ambiguous or Could not deduce (a1 ~ a).
P. S. It's ex. 1.29 from SICP.
Update
Final answer is:
cube :: Num a => a -> a
cube x = x * x * x
sum' :: (Int -> Double) -> Int -> (Int -> Int) -> Int -> Double
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral :: (Double -> Double) -> Double -> Double -> Int -> Double
integral f a b n = (h / 3) * sum' term 0 (+1) n where
h = (b - a) / n' where n' = fromIntegral n
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k'
| odd k = 4 * y k'
| even k = 2 * y k'
where k' = fromIntegral k
main = do
print $ integral cube 0 1 100 -- 0.25
print $ integral cube 0 1 1000 -- 0.25
print $ integral (\x -> 3 * x * x) 1 3 100 -- 26
/ is only used for types that are instances of Fractional, for Integral types use quot. You can use quot as an infix operator using backticks:
h = (b - a) `quot` n
The types of the two are
(/) :: Fractional a => a -> a -> a
quot :: Integral a => a -> a -> a
There are no types that are instances of both Fractional and Integral, which is why none of the type signatures would work. Unfortunately GHC doesn't know that it's impossible for a type to be an instance of both classes, so the error messages are not very intuitive. You get used to the style of GHC error messages though, and the detail they give helps a lot.
Also, as was suggested in the comments, I completely agree that all top level definitions should be given type signatures (including main). It makes error messages a lot easier to read.
Edit: Based on the comments below, it looks like what you want is something more like this (type signature-wise)
cube :: Num a => a -> a
sum' :: (Int -> Double) -> Int -> (Int -> Int) -> Int -> Double
integral :: (Double -> Double) -> Double -> Double -> Int -> Double
You will need to use fromIntegral to convert from Int to Double in h and in k. The type errors should be at least a bit more readable with these type signatures though.