How to generate arbitrary two argument function with QuickCheck? - haskell

I am trying to test my implementation of zipWith using QuickCheck. My implementation, myZipWith, I would like to QuickCheck test by comparing to the standard function. Something like:
main = do
quickCheck (prop_myZipWith :: (Int -> Int -> Int) -> [Int] -> [Int] -> Bool)
prop_myZipWith :: (a -> b -> c) -> [a] -> [b] -> Bool
prop_myZipWith f x y = (myZipWith x y) == (zipWith f x y)
This does not work because (Int -> Int -> Int) is not an instance of Arbitrary.
With single-argument functions one can get around this using Test.QuickCheck.Function's Fun (which instantiates Arbitrary). For example:
main = do
quickCheck (prop_myMap :: Fun Int Int -> [Int] -> Bool)
prop_myMap :: Fun a b -> [a] -> Bool
prop_myMap (Fun _ f) l = (myMap f l) == (map f l)
I am trying to do something similar except generating two-argument arbitrary functions.
How can I generate arbitrary instances of two argument functions for QuickCheck testing of higher-order functions such as zipWith?

QuickCheck 2.9.2
With QuickCheck 2.9.2, you can use the Fun type, and the Fn pattern. You'll have to
import Test.QuickCheck.Function
You can then write the property using a tuple as input, and then curry the function:
prop_myZipWith :: Eq c => Fun (a, b) c -> [a] -> [b] -> Bool
prop_myZipWith (Fn f) x y = myZipWith (curry f) x y == zipWith (curry f) x y
main looks like this:
main =
quickCheck (prop_myZipWith :: Fun (Int, Int) Int -> [Int] -> [Int] -> Bool)
This compiles, and the test passes, in my repro.
QuickCheck 2.10.0.1
With QuickCheck 2.10.0.1, you can instead use the Fn2 pattern, like this:
prop_myZipWith :: Eq c => Fun (a, b) c -> [a] -> [b] -> Bool
prop_myZipWith (Fn2 f) x y = myZipWith f x y == zipWith f x y
The main method remains the same, because the type of prop_myZipWith hasn't changed, but import Test.QuickCheck.Function is no longer required.

Related

Haskell: Property Based Testing for Higher Order Function

I have two properties that a function foo must satisfy:
prop_1 :: [Int] -> Bool
prop_1 xs = foo xs id == xs
prop_2 :: [Int] -> (Int -> Int) -> (Int -> Int) -> Bool
prop_2 xs f g = foo (foo xs f) g == foo xs (g . f)
I am trying to check whether the above properties satisfy the following function using quickCheck:
foo :: [a] -> (a -> b) -> [b]
foo xs f = []
When I tried running quickCheck with prop_2 I get the following error:
quickCheck(prop_2)
<interactive>:18:1: error:
No instance for (Show (Int -> Int))
arising from a use of 'quickCheck'
(maybe you haven't applied a function to enough arguments?)
In the expression: quickCheck (prop_2)
In an equation for 'it': it = quickCheck (prop_2)
I am not sure why I am getting this error and how I can resolve it. Any insights are appreciated.
You can use QuickCheck's support for generation of random shrinkable, showable functions by changing the property to
prop_2 :: [Int] -> Fun Int Int -> Fun Int Int -> Bool
prop_2 xs (Fn f) (Fn g) = foo (foo xs f) g == foo xs (g . f)
and then you'll see something more useful than <function> for counterexamples.
As the documentation on QuickCheck says:
However, before we can test such a property, we must see to it that function values can be printed (in case a counter-example is found). That is, function types must be instances of class Show. To arrange this, you must import module ShowFunctions into every module containing higher-order properties of this kind. If a counter-example is found, function values will be displayed as "<function>"
So you can fix this by importing a module like:
import Text.Show.Functions
prop_1 :: [Int] -> Bool
prop_1 xs = foo xs id == xs
prop_2 :: [Int] -> (Int -> Int) -> (Int -> Int) -> Bool
prop_2 xs f g = foo (foo xs f) g == foo xs (g . f)

How To Properly Choose Which USB Device To Connect To?

I am new to both USB drivers and Haskell. I am trying to connect to Tomu (an ARM micocontroller that fits in a USB port) using System.USB. I tried this example: https://github.com/basvandijk/usb-example/blob/master/example.hs, but it is several years out of date. I am trying to do hello world on USB, but getting type errors.
The following code works:
module Lib where
import System.USB
import System.USB.IO
import Data.Vector
import Data.Maybe
getOneDesc :: Int -> IO (VendorId, ProductId)
getOneDesc n = do
usbConn <- newCtx
devList <- getDevices usbConn
f <- getDeviceDesc $ devList ! n
let f0 = deviceVendorId f
let f1 = deviceProductId f
return (f0, f1)
At the repl, I can type getOneDesc 0 and I get something like this:
(300, 42)
I figured I ought to be able to do something like this:
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> Bool
isThisDeviceTheOneIWant n a b = do
(x, y) <- getOneDesc n
return (x == a) && (y == b)
But I encounter type errors.
Can anybody see what's wrong with this?
Your getOneDesc is an IO (VendorId, ProductId), so that means that the result type of your return (x == a) && (y == b) has type IO Bool. So you should change the type of your function. You must also add parentheses around the argument you pass to return (because in Haskell, return is not a keyword, just a plain function).
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> IO Bool
isThisDeviceTheOneIWant n a b = do
(x, y) <- getOneDesc n
return ((x == a) && (y == b))
You can not make the isThisDeviceTheOneIWant return a Bool, since the getOneDesc returns an IO (VendorId, ProductId), and you can not get an a out of an IO a.
We can, like #DanielWagner says, use fmap :: Functor f => (a -> b) -> f a -> f b to process the result of the getOneDesc n, like:
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> IO Bool
isThisDeviceTheOneIWant n a b = fmap ((a, b) ==) (getOneDesc n)
or use (<$>) :: Functor f => (a -> b) -> f a -> f b which is the same as fmap:
isThisDeviceTheOneIWant :: Int -> VendorId -> ProductId -> IO Bool
isThisDeviceTheOneIWant n a b = ((a, b) ==) <$> getOneDesc n

Generalize function to fold both elements with one higher-kinded type and with two nested types?

I have next two elements:
x :: Maybe t
y :: [(String, t)]
And I have a function:
foo :: t -> a
How can I implement polymorphic function that can work both on x and y with foo to collect results in list? More specifically, I need to put something instead of ??? here:
mapToList :: ??? => (t -> a) -> ??? t -> [a]
And I want to call with less boilerplate possible, most closest option to this is preferable:
mapToList foo x
mapToList foo y
Something naive like this doesn't work :(
mapToList :: Foldable f => (t -> a) -> f t -> [a]
mapToList extractor = map extractor . toList
mapToList #Maybe foo x
mapToList #([] ((,) String)) foo y
I was looking at Compose but didn't manage to figure out how to apply it to my problem in nice simple way. I can use Compose to generalize somehow but my solution is not satisfactory. I can always use map for lists and just maybe [] foo on Maybe's. But I wonder, is there nice way to generalize both use cases?
Not sure this helps at all since it's just shifting the boilerplate away from the call site, but:
{-# LANGUAGE FlexibleInstances,FunctionalDependencies,RankNTypes #-}
import Data.Functor.Compose (Compose(Compose))
import Data.Foldable
class AsFoldable x a | x -> a where
withFoldable :: (forall f. (Foldable f) => f a -> b) -> x -> b
instance AsFoldable [(String,a)] a where
withFoldable f = f . Compose
instance AsFoldable (Maybe a) a where
withFoldable = id
x :: Maybe Int
x = Just 3
y :: [(String,Int)]
y = [("A",5),("B",6)]
mapToList :: (AsFoldable x t) => (t -> a) -> x -> [a]
mapToList f = withFoldable (map f . toList)
main = do
print $ mapToList (+1) x
print $ mapToList (+1) y

How to get properties of functions

I have functions with two different type signatures:
f :: Int -> [a] -> [a]
g :: (Int, Int) -> [a] -> [a]
The first parameter determines the length of the list that the function operates on. For example, f might operate on lists of length p-1 and g operates on lists of length p^(e-1) for first arguments p and (p,e) respectively.
I use f and g as arguments to another function h :: Int -> ([a] -> [a]) -> [a] -> [a] which needs to know this length function (h's first argument). What I find myself doing currently is:
\p -> h (p-1) (f p)
\(p,e) -> h (p^(e-1)) (g (p,e))
everywhere I use h in combination with f and g. This duplication is error prone and messy.
The goal is to find a way to avoid passing the length argument to h. Instead, h should be able to determine the length itself based on the function argument.
One non-solution would be to change the definition of f to:
f' :: (Int, Int) -> [a] -> [a]
f' (2,_) = previous def
f' (p,_) = previous def
funcToLen :: ((Int, Int) -> [a] -> [a]) -> (Int, Int) -> Int
funcToLen f' (p,_) = p-1
funcToLen g (p,e) = p^(e-1)
h' :: (Int, Int) -> ((Int, Int) -> [a] -> [a]) -> [a] -> [a]
h' (p,e) func xs = let len = funcToLen func
func' = func (p,e)
in previous def
-- usage
(\p -> h' (p,??) f')
(\(p,e) -> h' (p,e) g)
This has several drawbacks:
I have to change the first argument of f, and then ignore the second part of the tuple
When I actually use h' with f', I have to create a dummy argument for the second part of the tuple
Most importantly, funcToLen doesn't work because I can't pattern match on function names.
Another solution that actually works is to use Either:
f' :: Int -> (Int, [a] -> [a])
f' 2 xs = (1, previous def)
f' p xs = (p-1, previous def)
g' :: (Int, Int) -> Either Int ([a] -> [a])
g' (p,1) xs = (1, previous def)
g' (p,e) xs = (p^(e-1), previous def)
h' :: (Int, ([a] -> [a])) -> ([a] -> [a])
h' ef = let len = fst ef
f = snd ef
in previous def
This also has a few downsides:
The length function is duplicated for each pattern of f' and g'
The type signatures of f', g', and h' are all uglier
I can't immediately use f' and g' on their own (i.e. not as arguments to h'). Instead I have to peel off the tuple.
I'm looking for ways to clean this up so that I don't have to duplicate the length function everywhere, but also allows me to use the functions f and g' in the expected way. I expect this problem has been "solved" before, but I don't know quite what I should be looking for.
If you create a function c that calculates p^e-1, effectively decoupling this operation from f and g:
c :: (Int, Int) -> Int
c (p, e) = p ^ (e - 1)
you can merge f and g into the same function (by simply eliminating g). When you have to convert a tuple into an Int, you use c.
The implementation of h is also trivial and does not contain duplicated code.

Using map with two lists rather than one. Can you nest?

I need to run a function that takes two arguments several times. I have two lists containing these arguments and I'd like to be able to use map or something similar to call the function with the corresponding args.
The function I want to call has this type:
runParseTest :: String -> String -> IO()
The lists are created like this:
-- Get list of files in libraries directory
files <- getDirectoryContents "tests/libraries"
-- Filter out ".." and "." and add path
let names = filter (\x -> head x /= '.') files
let libs = ["tests/libraries/" ++ f | f <- names]
So lets say that names contains ["test1.js", "test2.js", "test3.js"] and libs contains ["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]
I want to call them like this:
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
I know I could create a helper function that does this fairly easily, but out of interest, is it possible to do in one line using map?
This is what I have so far, but obviously the first argument is always "test":
mapM_ (runParseTest "test") libs
I apologise if this is unclear. I can provide more info if necessary.
This is a great time to use Hoogle! Hoogle is a search engine for searching Haskell types. For instance, a Hoogle query for (a -> b) -> [a] -> [b] pulls up map. Here, you have a function of type String -> String -> IO (); you want a function of type (String -> String -> IO ()) -> [String] -> [String] -> IO (). Hoogle can often generalize by itself, but it's having trouble here, so let's help it out: You just want (a -> a -> IO ()) -> [a] -> [a] -> IO () for any a. If you Hoogle for that type signature, the first result is zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m () in the Control.Monad module, which does exactly what you want. This is part of a family of functions, with varying degrees of generality:
zip :: [a] -> [b] -> [(a,b)], which pairs up two lists, truncating the shorter one.
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c], which runs a supplied function on elements from each of the two lists; zip = zipWith (,).
zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c], which is like zipWith inside a monad; zipWithM f xs ys = sequence $ zipWith f xs ys.
zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m (), which is like zipWithM but discards its result; zipWithM_ f xs ys = zipWithM f xs ys >> return () = sequence_ $ zipWith f xs ys.
zip3 :: [a] -> [b] -> [c] -> [(a, b, c)], whose functionality I'm sure you can figure out :-)
zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d], which is like zipWith on three lists; zipWith3 = zip (,,).
A family of zipN and zipWithN functions in Data.List, going up through zip7/zipWith7. (Arguably, this starts with id :: [a] -> [a] as zip1 and map :: (a -> b) -> [a] -> [b] as zipWith1, which is where your question comes from.)
And, in greatest generality, the ZipList applicative functor. Given some lists xs1…xsN, then runZipList $ f <$> ZipList xs1 <*> ZipList xs2 <*> ... <*> ZipList xsN = runZipList $ liftAN f (ZipList xs1) ... (ZipList xsN) behaves just like zipWithN f xs1 ... xsN.
So, in your specific use case, we're going to have—with a few extra changes—the following:
import Data.List (isPrefixOf)
...
-- I got rid of `head` because it's a partial function, and I prefer `map` to
-- list comprehensions for simple things
do files <- getDirectoryContents "tests/libraries"
let names = filter (not . ("." `isPrefixOf`)) files
libs = map ("tests/libraries/" ++) names
zipWithM_ runParseTest names libs
So lets say that names contains ["test1.js", "test2.js", "test3.js"]
and libs contains ["tests/libraries/test1.js", "tests/libraries/test2.js", "tests/libraries/test3.js"]
I want to call them like this:
runParseTest "test1.js" "tests/libraries/test1.js"
runParseTest "test2.js" "tests/libraries/test2.js"
runParseTest "test3.js" "tests/libraries/test3.js"
It's possible to do that with zip:
map (\(a,b) -> runParseTest a b) $ zip names libs
Or maybe uncurry runParseTest:
map (uncurry runParseTest) $ zip names libs
Or with zipWith:
zipWith runParseTest names libs
And like Ozgur said, there are some analogues for monads:
> :t zipWithM
zipWithM :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]
> :t zipWithM_
zipWithM_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
You are looking for zipWithM_.
You say you could write a helper function which does this. Which means you know the type of the function you are looking for. In such cases you can use hoogle.
(Try: Monad m => [a] -> [b] -> m ())
While waiting for answers I created a solution of my own with a new function called map2M_ based on the source code for map and mapM_:
map2 :: (a -> b -> c) -> [a] -> [b] -> [c]
map2 _ [] _ = []
map2 _ _ [] = []
map2 f (a:as) (b:bs) = f a b : map2 f as bs
map2M_ :: Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()
map2M_ f as bs = sequence_ (map2 f as bs)

Resources