I was trying to write a QuickCheck test for the identity
f $ y = f y
My initial plan was to write an arbitrary generator that returns functions & Integer, having the signature Gen (Int -> Int, Int)
and in the prop_DollerDoesNothing test that function application with / without the $ gives the same result.
This was my code:
prop_DollarDoesNothing :: Property
prop_DollarDoesNothing =
forAll arbitraryFuncInt (\(f, y) -> (f $ y) == (f y))
arbitraryFuncInt :: Gen (Int -> Int, Int)
arbitraryFuncInt = do
f <- elements [(\x -> x*2), (\x -> x+3), (\x -> x-2)]
y <- arbitrary :: Gen Int
return (f, y)
And it generated the following helpful error message:
* No instance for (Show (Int -> Int))
arising from a use of `forAll'
(maybe you haven't applied a function to enough arguments?)
* In the expression:
forAll arbitraryFuncInt (\ (f, y) -> (f $ y) == (f y))
In an equation for `prop_DollarDoesNothing':
prop_DollarDoesNothing
= forAll arbitraryFuncInt (\ (f, y) -> (f $ y) == (f y))
So, I fixed the error and got the test working by applying the arbitrary function and returning a pair of ints from arbitraryFuncInt
prop_DollarDoesNothing :: Property
prop_DollarDoesNothing =
forAll arbitraryFuncInt (\(x, y) -> x == y)
arbitraryFuncInt :: Gen (Int, Int)
arbitraryFuncInt = do
f <- elements [(\x -> x*2), (\x -> x+3), (\x -> x-2)]
y <- arbitrary :: Gen Int
return (f $ y, f y)
My questions are:
is it simply not possible to return arbitrary functions that aren't fully applied due to not having an instance for Show?
Can I write an instance for Show (Int -> Int) to make # 1 possible?
Can QuickCheck generate arbitrary functions given a type signature, for cases where I'm testing identities that are true for all functions (of a given type). Above, I specify the 3 test functions by hand, I'd like to automate that somehow, ideally something like this f <- arbitrary :: Gen (Int -> Int)
QuickCheck has support to generate, shrink and show functions, using the Fun type. CoArbitrary enables generation of functions. It is then converted to a (possibly infinite) trie-like structure, that can be inspected and shrunk to a finite value (because a test failure only depends on finitely many inputs), which can then be shown as a counterexample.
Concretely, you can write properties as function that take a Fun argument, which is a wrapper around (->) using the mechanism I described. Deconstruct it with the Fn pattern to get a function.
prop_dollarDoesNothing :: Property
prop_dollarDoesNothing = property $ \(Fn (f :: Int -> Int)) x ->
(f $ x) === f x
For more information
The QuickCheck implementation: https://hackage.haskell.org/package/QuickCheck-2.11.3/docs/Test-QuickCheck-Function.html
The paper "Shrinking and showing functions" by Koen Claessen, which appears to be paywalled, but his talk is online: https://www.youtube.com/watch?v=CH8UQJiv9Q4
Arbitrary can generate functions just fine (provided the arguments are instances of CoArbitrary), it's just the showing part that doesn't work. There's not really a good way to show a function.
This is a common problem, and therefore QuickCheck provides the Blind modifier. It basically fakes a Show instances for any type, not actually showing any information about the value. Of course this somewhat diminishes the debugging-usefulness of a failing test case, but there's not much that can done about this.
Related
plusOne :: [[(Int, Int, Int)]] -> [[(Int, Int, Int)]]
Given a list of lists of 3-tuples.
If I want to iterate through the list and +1 to the Int values, how should I approach this? I'm not sure if this is a scenario where Maps should be used or not.
Can someone point me into the right direction?
Split the functions. The lists are easy; one map each. But tuples don't traverse the way they do in e.g. Python, so they require unpacking to access the elements; this is possible with generic programming but far easier with pattern matching. Tuples can hold fields of varying types, so something like map couldn't access all of them. We can make our own map-analogue for triples specifically:
map3t :: (x -> y) -> (x, x, x) -> (y, y, y)
map3t f (a, b, c) = (f a, f b, f c)
Now we can inspect each level of our type and handle it separately:
op :: Int -> Int
op = (+1)
t3 :: (Int, Int, Int) -> (Int, Int, Int)
t3 = map3t op
lt3 :: [(Int, Int, Int)] -> [(Int, Int, Int)]
lt3 = map t3
llt3 :: [[(Int, Int, Int)]] -> [[(Int, Int, Int)]]
llt3 = map lt3
This is not recursion, although map may be implemented using recursion (Data.List.map is). Each function calls a different function for the inner level.
Here is an example of a not very generic way of how we can use map to access nested lists,which also can be matched on 3tuples with a lambda function:
fun :: (Num a, Num b, Num c) => [[(a, b, c)]] -> [[(a, b, c)]]
fun xs = map (map(\(x,y,z) -> (x+1,y+1,z+1))) xs
Pros: En easy and understandable oneliner to solve a specific problem
Cons: Not generic for the function applied to the elements, can become fuzzy and out of hand with more complex and bigger input structures.
Mapping with a hard coded function forcing you to make a new map for each operation. So a better way in that case would be to refactor the function itself, ie :
fun2 f xs = map (map(op f)) xs
where
op f' (x,y,z) = (f' x,f' y, f' z)
Making op a function to which you can give an operation for the specific type.
Making the signature for the function more generic on the types of operations: (Notice here that we can no longer be sure of the type of x,y,z, which before were numerics (because of the +1 operation) giving us a more generic version of the function, but also making us more responsible of matching the types correctly, no string operations on integers etc.)
fun2 :: (t -> c) -> [[(t, t, t)]] -> [[(c, c, c)]]
Define a proper functor to wrap your tuples.
data Three a = Three {getThree :: (a, a, a)} deriving (Show, Functor)
If you don't want to use the DeriveFunctor extension, the definition is simple:
instance Functor Three where
fmap f (Three (x, y, z)) = Three (f x, f y, f z)
Then you can simply define plusOne as
>>> plusOne = let f = getThree . fmap (+1) . Three in fmap (fmap f)
where f is a function that wraps a 3-tuple, maps (+1) over each element, and unwraps the result. This gets mapped over your list of lists:
> x = [[(1, 2, 3), (4,5,6)], [(7,8,9)]]
> plusOne x
[[(2,3,4),(5,6,7)],[(8,9,10)]]
You can also use Data.Functor.Compose to eliminate one of the levels of fmap (or, at least hide it behind another set of names to break up the monotony):
> getCompose . fmap (getThree . fmap (+1) . Three) . Compose $ x
[[(2,3,4),(5,6,7)],[(8,9,10)]]
We've applied the same pattern of wrapping/fmaping/unwrapping twice. We can abstract that away with a helper function
-- wrap, map, and unwrap
wmu pre post f = post . fmap f . pre
plusOne = wmu Compose getCompose $ wmu Three getThree $ (+1)
One might notice a similarity between wmu and dimap (specialized to (->)):
wmu pre post = dimap pre post . fmap
Everything is even simpler if you can replace the generic tuple with a custom product type in the first place.
data Triplet a = Triplet a a a
-- Can be derived as well
instance Functor Triplet where
fmap f (Triplet x y z) = Triplet (f x) (f y) (f z)
plusOne :: [[Triplet Int]] -> [[Triplet Int]]
plusOne = fmap (fmap (fmap (+1)))
Suppose that I am writing tests for Data.Set. I would like to check that deleting elements from the set works, and so I might write something like this:
prop_deleteA it x = member x it ==> not (member x (delete x it))
assuming that it has a suitable Arbitrary instance. However, this relies on quickcheck generating values of x that happen to exist within the set, which is not in general guaranteed. It would be much better if x could be made to depend on it so as to guarantee that x is already a member of it. How might I do this?
I had the thought that I could write
prop_deleteB it f = let x = f it
in not (member x (delete x it))
where f :: Set a -> a is suitably defined by means of coarbitrary. However, coarbitrary would only allow us to define f :: Set a -> b, which unfortunately isn't what we want. My best thought so far has been to define a new type
data SetAndElement a = SetAndElement (Set a) a
which allows us to write a suitable Arbitrary instance
instance (Ord a, Arbitrary a) => Arbitrary (SetAndElement a) where
arbitrary = do it <- suchThat arbitrary (not . Set.null)
x <- elements (elems it)
return (SetAndElement it x)
allowing prop_delete to be written as
prop_deleteC (SetAndElement it x) = not (member x (delete x it))
This works, but seems a little involved; are there any better options? (If not, I'll modify the question and put this as an answer.) The actual Data.Set implementation (containers package) tests deletion by checking that (delete x) . (insert x) == id if x was not already a member of the given set.
It depends on what generators you have available. For example, if you already have setOf1 (generates a Set with at least one element) and setElements (takes elements from a Set), it can be written with forAll:
-- example implementations of both combinators
setOf1 :: (Arbitrary a, Ord a) => Gen a -> Gen (Set a)
setOf1 = fmap fromList . listOf1
setElements :: Set a -> Gen a
setElements = elements . toList
prop_delete =
forAll (setOf1 arbitrary) $ \theSet ->
forAll (setElements theSet) $ \x ->
not (member (x :: Int) (delete x theSet))
This is mostly the same as SetAndElement, but instead of a fixed data type, we're using re-usable functions that can be used for further tests:
prop_null = forAll (setOf1 (arbitrary :: Gen Integer)) $ not . null
However, even if you don't write setOf1 or setElements, forAll can be rather succinct for simple tests:
prop_delete :: (Arbitrary a, Ord a) => (NonEmptyList a) -> Property
prop_delete (NonEmpty xs) =
let theSet = fromList xs
in forAll (elements xs) $ \x ->
not (member x (delete x theSet))
If you provide setElements and NonEmptySet, this can be written as
newtype NonEmptySet x = NonEmptySet {getNonEmptySet :: Set a}
instance (Ord a, Arbitray a) => Arbitrary (NonEmptySet a) where
arbitrary = fmap NonEmptySet . setOf1 $ arbitrary
prop_delete :: (Arbitrary a, Ord a) => (NonEmptySet a) -> Property
prop_delete (NonEmptySet theSet) =
forAll (setElements theSet) $ \x ->
not (member x (delete x theSet))
That way you can use NonEmptySet for tests that require a non-empty set, and setElements only for those where you actually need to choose an element at random.
This works in the ghci
data MyList a = Empty | Cons a (MyList a) deriving (Show, Eq, Read, Ord)
let x = Cons(21, Cons(12, Empty))
However when I type:
Prelude> x
I get this error:
No instance for (Show (MyList (Integer, MyList (Integer, MyList a0) ->
MyList (Integer, MyList a0)) ->
MyList (Integer, MyList (Integer, MyList a0) ->
MyList (Integer, MyList a0)))) arising from a use of `print'
You are using the wrong syntax for function application. The following code does what you want:
let x = Cons 21 (Cons 12 Empty)
The reason for this is that the Cons constructor is a curried function, but you are treating it as an uncurried function.
Curried functions
Consider the following function adding two integers:
add :: Int -> (Int -> Int)
add = \x -> (\y -> x + y)
Here we say add is a function, which takes an argument x of type Int and returns a function,
which takes an argument y of type Int and returns x + y of type Int.
We can apply this function for example as (add 1) 2 evaluating to 3.
Function application is left-associative in Haskell, which means that we don't need the parentheses
in (add 1) 2 and can simply write add 1 2.
The function type constructor -> is right-associative in Haskell, which means that we don't need the parentheses in add :: Int -> (Int -> Int) and can simply write add :: Int -> Int -> Int.
Also we don't have to explicitly define add using lambdas and can use the following notation:
add :: Int -> Int -> Int
add x y = x + y
Encoding multi-parameter functions as single-parameter functions returning single-parameter functions is quite common in Haskell. This approach has the nice property, that we can also partially apply a function. For example the following function takes a single Int and adds 2:
add2 :: Int -> Int
add2 x = add 2 x
But we can also partially apply add and simply write:
add2 :: Int -> Int
add2 = add 2
This is also called point-free notation, where parameters are referred to as points.
Uncurried functions
An alternative encoding of multi-parameter functions can be done using tuple-values, i.e.
add' :: (Int, Int) -> Int
add' (x, y) = x + y
We can invoke this function for example as add' (2, 3), which constructs the pair (2, 3) :: (Int, Int) and passes it as a single argument to the add' function.
Uncurried <-> Curried
In the standard library are two functions to convert functions between the two styles.
curry :: ((a, b) -> c) -> a -> b -> c
curry f x y = f (x, y)
uncurry :: (a -> b -> c) -> (a, b) -> c
uncurry f (x, y) = f x y
For example curry add' gives us add, and uncurry add gives us add'.
Back to explaining ghci's rambling
Note that we could also write the uncurried application as add'(2, 3), which together with partial application and polymorphism explains why let x = Cons(21, Cons(12, Empty)) doesn't directly lead to an error, but ghci subsequently says misterious things about the evaluation of x.
What happens here is that (12, Empty) is pair of type (Int, MyList a) for some type a.
This pair is then used as the first argument in Cons (12, Empty), so we get a partially applied function which takes
a MyList (Int, MyList a) and appends (12, Empty) as an element to this list.
The same happens for Cons(21, Cons(12, Empty)) where we partially apply a pair of 21 and the before mentioned partial function. In the end we tell ghci to print a function, which it cannot display and hence complains about a missing Show instance for the corresponding function type.
I'm trying to write a QuickCheck property that takes one or more functions as input. To keep things simple, consider a property to check that function composition is equivalent to successive function application, and a quick-and-dirty test driver:
import Test.QuickCheck
prop_composition :: (Int -> Int) -> (Int -> Int) -> Int -> Bool
prop_composition f g x = (f . g) x == f (g x)
main :: IO ()
main = quickCheck prop_composition
Unfortunately, this doesn't compile, because the inputs to a property need to implement Show so that QuickCheck can report what inputs caused the failure, but there's no Show implementation for functions:
Test.hs:10:7:
No instance for (Show (Int -> Int))
arising from a use of `quickCheck' at Test.hs:10:7-33
Possible fix: add an instance declaration for (Show (Int -> Int))
In the expression: quickCheck prop_composition
In the definition of `main': main = quickCheck prop_composition
I've tried writing my own do-nothing instance of Show for functions...
instance Show (a -> b) where
show _ = "[func]"
... which compiles, but triggers a warning with -Wall...
Test.hs:3:9: Warning: orphan instance: instance Show (a -> b)
... which makes me think there's a more correct way to do this.
My gut tells me the answer lies in the Test.QuickCheck.Function module, but it's undocumented, and I can't figure out just from looking at the type signatures what anything in there is for or how it's intended to be used.
You are right Test.QuickCheck.Function is the right answer.
You just change the types:
prop_composition :: Fun Int Int -> Fun Int Int -> Int -> Bool
prop_composition f g x = ((apply f) . (apply g)) x == (apply f) ((apply g) x)
The import Text.Show.Functions could also be used with keeping the original signature.
I want to create a function apply that takes a function with an arbitrary amount of arguments as well as a list of integers, and returns the result of the function (Where each integer in the list is an argument in order.
I was thinking something like:
apply :: ([Int] -> Int) -> [Int] -> Int
apply f x:xs = apply (f x) xs
apply f [] = f
But I know this won't work because the type signature is wrong - the function doesn't take a list of ints, it just takes some amount of int arguments.
Additionally, when I get to the base case the f argument to apply should actually be an integer, violating the type signature anyway.
Does anyone know how to deal with this sort of problem?
I want to create a function apply that takes a function with an arbitrary amount of arguments as well as a list of integers,
Why do you want to do this? Perhaps your argument structure should be passed as a data structure, but so far you've over constrained the problem to ensure it won't produce an idiomatic Haskell solution.
You can do it with some fancy type classes
{-# LANGUAGE FlexibleInstances #-}
-- for ApplyType (Int -> r)
class ApplyType t where
apply :: t -> [Int] -> Int
instance ApplyType Int where
apply f _ = f
instance (ApplyType r) => ApplyType (Int -> r) where
apply f (x:xs) = apply (f x) xs
main :: IO ()
main = do print $ apply ((+) :: Int->Int->Int) [1, 2]
print $ apply ((\x y z w -> x*y - z`div`w) :: Int->Int->Int->Int->Int) [3,5,8,2]