Lazy Evaluation when Multiplying with Zero - haskell

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

Related

Haskell: using (fromInteger (a `div` b) / 1 == a / b) as guard?

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)

convert bit to int forward with foldr

bit array right to left, e.g. [0,1,0,1] = 10 can be read with:
binToInt = foldr (\x xs -> x + 2 * xs) 0
I would like to read it left to right, e.g. [1,0,1,0] = 10
I thought this would work:
binToInt' = foldr (\x xs -> (x * ((^) 2 (length xs)) + xs) 0
however I get the error:
Couldn't match type `t0 a0' with `Int'
what am I doing wrong?
(as a work around I am reversing the result of binToInt)
I solved my problem:
binToInt' = foldl (\acc x -> x + 2 * acc) 0
which unfolds to:
f = (\acc x -> x + 2 * acc)
foldl f 0
[1,0,1,0]
(f [1,0,1]) * 2 + 0
((f [1,0]) * 2 + 1) * 2 + 0
(((f [1]) * 2 + 0) * 2 + 1) * 2 + 0
((((f []) * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 0
((((0) * 2 + 1) * 2 + 0) * 2 + 1) * 2 + 0

Implementing Haskell Logarithm function

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 ;)

How can I use Haskell Memoize to solve LCS?

Here is the code:
import Data.Function.Memoize
main = do
let
f 0 0 = 0
f 0 _ = 0
f _ 0 = 0
f n m = if a !! n == b !! m
then 1 + f' (n-1) (m-1)
else max (f' (n-1) m) (f' n (m-1))
f' = memoize2 $ f
print $ length a
print $ length b
print $ f (length a - 1) (length b - 1)
where
a = "1234helloworld2ffdfdfdf32rg4364jm5"
b = "03424helloworldfdfdfdfd4353645645jnt"
But the problem is I cannot write the function globally where strings a and b are passed to it as arguments. It seems if I rewrite
f n m
to
f a b n m
and
f' = memoize4 f
the function will speed down.
How can I pass arguments that should not be used in memoization to functions that use memoize?
so I write my global function like this and it does work!
But how can I accumulate the common string it finds and get the final result with this function?
lcs a b = f (length a - 1) (length b - 1)
where
f 0 0 = 0
f 0 _ = 0
f _ 0 = 0
f n m = if a !! n == b !! m
then (1 + f' (n-1) (m-1))
else max (f' (n-1) m) (f' n (m-1))
f' = memoize2 $ f

How do I transform a function defined with pattern matching into an equivalent lambda?

How do I write
f 0 = 1
f x = (f(x-1))*2 + 2
as a lambda in Haskell?
Thanks in anticipation.
You'd move the pattern matching from the right and use a case expression
f = \ x -> case x of
0 -> 1
x -> f (x-1) * 2 + 1
f = \x -> if x == 0 then 1 else (f (x - 1)) * 2 + 2

Resources