I have a bunch of QuickCheck properties defined as follows:
...
prop_scaleData3 d n = n > 1 ⇛ length (scaleData d n) ≡ n
prop_scaleData4 d n = n > 1 ⇛ head (scaleData d n) ≡ -d
prop_scaleData5 d n = n > 1 ⇛ last (scaleData d n) ≡ d
...
That's a lot of repetition. What would be the right way to DRY it up?
What about something like
gt1 :: (Integer -> Prop) -> Prop
gt1 f = forAll $ \(Positive n) -> f $ n + 1
Then your properties become
prop_scaleData3 d = gt1 $ \n -> length (scaleData d n) ≡ n
prop_scaleData4 d = gt1 $ (≡ -d) . head . scaleData d
prop_scaleData5 d = gt1 $ (≡d) . last . scaleData d
This avoids the duplicated logic. Whether or not you like the pointfree stuff is up to you :)
prop_scaleData3 d n = n > 1 ==> length (scaleData d n) == n
prop_scaleData4 d n = n > 1 ==> head (scaleData d n) == -d
prop_scaleData5 d n = n > 1 ==> last (scaleData d n) == d
Just observe what is similar about these three functions and make a new helper function that extracts out the commonalities. For example:
scaleProp :: Int -> Int -> ([Int] -> Int) -> Int -> Bool
scaleProp d n op res = n > 1 ==> op (scaleData d n) == res
Then you can express your original props in terms of the helper:
prop_scaleData3 d n = scaleProp d n length n
prop_scaleData4 d n = scaleProp d n head (-d)
prop_scaleData4 d n = scapeProp d n last d
At this point the repetition isn't about logic so much as syntax (naming functions and applying arguments). In such cases I don't feel the DRY principle is really helpful - you can make less syntactic repetition but you'll lose readability or modularity. For example, Toxaris combined the solutions into one function; we can do the same but lets do it in a simpler way with just lists of booleans:
prop_scaleData345 d n =
let sp = scaleProp d n
in and [sp length n, sp head (-d), sp last d]
-- or instead:
-- in all (uncurry sp) [(length, n), (head, negate d), (last, d)]
If you put this pragma at the top of your file:
{-# LANGUAGE ParallelListComp #-}
You might be able to do something like this with GHC:
prop_scaleData345 d n = n > 1 => conjoin
[ f (scaleData d n) == x
| f <- [length, head, last]
| x <- [n , -d , d ]
]
This should generate a list of three properties, and then say that all of them have to be true. The first property uses f = length and x = n, the second property uses f = head and x = -d, and the last property uses f = last and x = d.
Related
I am trying to solve the Codewars problem called: Number of trailing zeros of N! with Haskell.
I know that I don't need to calculate the factorial to know the trailing zeros and in fact I am just counting how many many numbers are divisible by 5 and how many times for each.
I have written 2 version, one that uses memoization when defactoring a number in order to get how many times is divisible by 5 and another one that do not use memoization.
What surprise me is that the supposed DP approach takes longer than the trivial recursive one. I am probably doing something very stupid in my code.
These are the functions:
zeros x = helperZeros [1..x]
helperZeros :: [Integer] -> Integer
helperZeros = sumArrayTuple . filter (\x -> x `mod` 5 == 0)
sumArrayTuple = foldl (\acc x -> acc + (fastDef x)) 0
data Tree a = Tree (Tree a) a (Tree a)
instance Functor Tree where
fmap f (Tree l m r) = Tree (fmap f l) (f m) (fmap f r)
index :: Tree Integer -> Integer -> Integer
index (Tree _ m _) 0 = m
index (Tree l _ r) n = case (n-1) `divMod` 2 of
(q,0) -> index l q
(q,1) -> index r q
nats = go 0 1
where
go n s = Tree (go l s') n (go r s' )
where
l = n + s
r = l + s
s' = s * 2
fastDef:: Integer -> Integer
fastDef x = trace (show x) index memTreetDef x
memTreetDef = fmap (defact fastDef) nats
defact f n
| n `mod` 5 /= 0 = 0
| otherwise = 1 + f (n `div` 5)
zeros' x = helperZeros' [1..x]
helperZeros' :: [Integer] -> Integer
helperZeros' = sumArrayTuple' . filter (\x -> x `mod` 5 == 0)
sumArrayTuple' = foldl (\acc x -> acc + (def x)) 0
def n
| n `mod` 5 /= 0 = 0
| otherwise = 1 + def (n `div` 5)
What I am trying to memoize is the result of the defact function, for example if I have already calculate defact 200, then it would reuse this result to calculate defact 1000.
I am fairly new to DP in Haskell.
If you are tested your code performance with trace and show here, that is the issue: they are very slow compared to the main code. If not, performance of variants must be about the same.
The def function is a poor candidate for memoization. The average depth of recursion is not very different from 1. The rest of the complexity is reduced to the operation mod, that is, the division that is hardly more expensive than table look up (and division by constant can be optimized to multiplication).
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
I am trying to build a data-structure in Haskell which functions can use to avoid re-computing values. For example, say I had the function:
f :: Int -> Int -> Int
f 1 1 == 1
f m n
| abs m > n = 0
| OTHERWISE if value of f m n has already been computed by another recursive branch, return that value and add it to the "database"
| OTHERWISE return f (m-1) (n-1) + f (m - 1) n
I have already looked at memoization, but haven't been able to implement a solution :\
Suggestions? :)
A great explanation is here.
I love memoize package :)
Example (solving the "A frog is jumping up the staircase..." problem):
import Data.Function.Memoize
ladder :: Integer -> Integer -> Integer
ladder n k = g n
where g = memoize f
f 0 = 1
f x = sum [g (x - y) | y <- [1..if x < k then x else k]]
When solving system of linear equations by Tridiagonal matrix algorithm in Haskell I met following problem.
We have three vectors: a, b and c, and we want to make a third vector c' which is a combination of them:
c'[i] = c[i] / b[i], i = 0
c'[i] = c[i] / (b[i] - a[i] * c'[i-1]), 0 < i < n - 1
c'[i] = undefined, i = n - 1
Naive implementation of the formula above in Haskell is as follows:
calcC' a b c = Data.Vector.generate n f
where
n = Data.Vector.length a
f i =
| i == 0 = c!0 / b!0
| i == n - 1 = 0
| otherwise = c!i / (b!i - a!i * f (i - 1))
It looks like this function calcC' has complexity O(n2) due to recurrence. But all we actualy need is to pass to inner function f one more parameter with previously generated value.
I wrote my own version of generate with complexity O(n) and helper function mapP:
mapP f xs = mapP' xs Nothing
where
mapP' [] _ = []
mapP' (x:xs) xp = xn : mapP' xs (Just xn)
where
xn = f x xp
generateP n f = Data.Vector.fromList $ mapP f [0 .. n-1]
As one can see, mapP acts like a standard map, but also passes to mapping function previously generated value or Nothing for first call.
My question: is there any pretty standard ways to do this in Haskell? Don't I reinvent the weel?
Thanks.
There are two standard function called mapAccumL and mapAccumR that do precisely what you want.
mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
mapAccumR :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
Basically, they behave like a combination of fold and map.
map f = snd . mapAccumL (\_ x -> (() , f x) ()
foldl f b = fst . mapAccumL (\b x -> (f b x, () ) b
If you use Data.Array, which is lazy, you can express the recurrence directly by referring to c' while defining c'.
Following code seems to be the simplest implementation of formula above in my case:
import qualified Data.Vector.Generic as V
calcC' a b c = V.postscanl' f 0.0 $ V.zip3 a b c
where
f c' (a, b, c) = c / (b - a * c')
Thanks to the authors of Vector who added helpfull postscanl' method.
Background
For fun, I'm trying to write a property for quick-check that can test the basic idea behind cryptography with RSA.
Choose two distinct primes, p and q.
Let N = p*q
e is some number relatively prime to (p-1)(q-1) (in practice, e is usually 3 for fast encoding)
d is the modular inverse of e modulo (p-1)(q-1)
For all x such that 1 < x < N, it is always true that (x^e)^d = x modulo N
In other words, x is the "message", raising it to the eth power mod N is the act of "encoding" the message, and raising the encoded message to the dth power mod N is the act of "decoding" it.
(The property is also trivially true for x = 1, a case which is its own encryption)
Code
Here are the methods I have coded up so far:
import Test.QuickCheck
-- modular exponentiation
modExp :: Integral a => a -> a -> a -> a
modExp y z n = modExp' (y `mod` n) z `mod` n
where modExp' y z | z == 0 = 1
| even z = modExp (y*y) (z `div` 2) n
| odd z = (modExp (y*y) (z `div` 2) n) * y
-- relatively prime
rPrime :: Integral a => a -> a -> Bool
rPrime a b = gcd a b == 1
-- multiplicative inverse (modular)
mInverse :: Integral a => a -> a -> a
mInverse 1 _ = 1
mInverse x y = (n * y + 1) `div` x
where n = x - mInverse (y `mod` x) x
-- just a quick way to test for primality
n `divides` x = x `mod` n == 0
primes = 2:filter isPrime [3..]
isPrime x = null . filter (`divides` x) $ takeWhile (\y -> y*y <= x) primes
-- the property
prop_rsa (p,q,x) = isPrime p &&
isPrime q &&
p /= q &&
x > 1 &&
x < n &&
rPrime e t ==>
x == (x `powModN` e) `powModN` d
where e = 3
n = p*q
t = (p-1)*(q-1)
d = mInverse e t
a `powModN` b = modExp a b n
(Thanks, google and random blog, for the implementation of modular multiplicative inverse)
Question
The problem should be obvious: there are way too many conditions on the property to make it at all usable. Trying to invoke quickCheck prop_rsa in ghci made my terminal hang.
So I've poked around the QuickCheck manual a bit, and it says:
Properties may take the form
forAll <generator> $ \<pattern> -> <property>
How do I make a <generator> for prime numbers? Or with the other constraints, so that quickCheck doesn't have to sift through a bunch of failed conditions?
Any other general advice (especially regarding QuickCheck) is welcome.
Here's one way to make a QuickCheck-compatible prime-number generator (stealing a Sieve of Eratosthenes implementation from http://en.literateprograms.org/Sieve_of_Eratosthenes_(Haskell)):
import Test.QuickCheck
newtype Prime = Prime Int deriving Show
primes = sieve [2..]
where
sieve (p:xs) = Prime p : sieve [x | x <- xs, x `mod` p > 0]
instance Arbitrary Prime where
arbitrary = do i <- arbitrary
return $ primes!!(abs i)
It can be used in QuickCheck like so:
prop_primes_dont_divide (Prime x) (Prime y) = x == y || x `mod` y > 0
For your use, you'd replace p and q with (Prime p) and (Prime q) in your property.
OK so here's what I did.
Top of file
{-# LANGUAGE NoMonomorphismRestriction #-}
import Test.QuickCheck
import Control.Applicative
All code as given in the question, except for prop_rsa. That was (obviously) heavily modified:
prop_rsa = forAll primePair $ \(p,q) ->
let n = p*q
in forAll (genUnder n) $ \x ->
let e = 3
t = (p-1)*(q-1)
d = mInverse e t
a `powModN` b = modExp a b n
in p /= q &&
rPrime e t ==>
x == (x `powModN` e) `powModN` d
The type for primePair is Gen (Int, Int), and the type for genUnder is Int -> Gen Int. I'm not exactly sure what the magic is behind forAll but I'm pretty sure this is correct. I've done some ad-hoc adjustments to 1) make sure it fails if I mess up the conditions and 2) make sure the nested forAll is varying the value of x across test cases.
So here's how to write those generators. Once I realized that <generator> in the documentation just meant something of type Gen a, it was cake.
genNonzero = (\x -> if x == 0 then 1 else x) `fmap` arbitrary
genUnder :: Int -> Gen Int
genUnder n = ((`mod` n) . abs) `fmap` genNonzero
genSmallPrime = ((\x -> (primes !! (x `mod` 2500))) . abs) `fmap` arbitrary
primePair :: Gen (Int, Int)
primePair = (,) <$> genSmallPrime <*> genSmallPrime
primePair took some trial and error for me to get right; I knew that some combinators like that should work, but I'm still not as familiar with fmap, <$> and <*> as I'd like to be. I restricted the computation to only select from among the first 2500 primes; otherwise it apparently wanted to pick some really big ones that took forever to generate.
Random thing to note
Thanks to laziness, d = mInverse e t isn't computed unless the conditions are met. Which is good, because it's undefined when the condition rPrime e t is false. In English, an integer a only has a multiplicative inverse (mod b) when a and b are relatively prime.