Make Test.QuickCheck.Batch use a default type for testing list functions - testing

I am testing a function called extractions that operates over any list.
extractions :: [a] -> [(a,[a])]
extractions [] = []
extractions l = extract l []
where extract [] _ = []
extract (x:xs) prev = (x, prev++xs) : extract xs (x : prev)
I want to test it, for example, with
import Test.QuickCheck.Batch
prop_len l = length l == length (extractions l)
main = runTests "extractions" defOpt [run prop_len]
But this won't compile; I have to supply a type either for run or prop_len, because QuickCheck can't generate [a], it has to generate something concrete. So I chose Int:
main = runTests "extractions" defOpt [r prop_len]
where r = run :: ([Int] -> Bool) -> TestOptions -> IO TestResult
Is there any way to get QuickCheck to choose a for me instead of having it specified in the type of run?

The quickcheck manual says "no":
Properties must have monomorphic types. `Polymorphic' properties, such as the one above, must be restricted to a particular type to be used for testing. It is convenient to do so by stating the types of one or more arguments in a
where types = (x1 :: t1, x2 :: t2, ...)
clause...

Related

How do I solve this ambiguous type variable error in Haskell?

I couldn't find an answer to my question among several ambiguous type variable error questions.
I'm currently trying to get this code I found to work. (https://gist.github.com/kirelagin/3886243)
My code:
import Control.Arrow
import Data.List
import qualified Data.Map as M
import Data.Function
main = do
putStrLn "Start test"
let foo = "Hello World"
let freqTest = freqList foo
putStrLn "Frequentie list"
print freqTest
putStrLn "Done.."
let treeTest = buildTree freqTest
putStrLn "Huffman Tree"
print treeTest
putStrLn "Done.."
let codeMaphTest = buildCodemap treeTest
putStrLn "Codemap ding"
-- print codeMaphTest
putStrLn "Done.."
--This typeclass is supposed to make life _a bit_ easier.
class Eq a => Bits a where
zer :: a
one :: a
instance Bits Int where
zer = 0
one = 1
instance Bits Bool where
zer = False
one = True
-- Codemap is generated from a Huffman tree. It is used for fast encoding.
type Codemap a = M.Map Char [a]
-- Huffman tree is a simple binary tree. Each leaf contains a Char and its weight.
-- Fork (node with children) also has weight = sum of weights of its children.
data HTree = Leaf Char Int
| Fork HTree HTree Int
deriving (Show)
weight :: HTree -> Int
weight (Leaf _ w) = w
weight (Fork _ _ w) = w
-- The only useful operation on Huffman trees is merging, that is we take
-- two trees and make them children of a new Fork-node.
merge t1 t2 = Fork t1 t2 (weight t1 + weight t2)
-- `freqList` is an utility function. It takes a string and produces a list
-- of pairs (character, number of occurences of this character in the string).
freqList :: String -> [(Char, Int)]
freqList = M.toList . M.fromListWith (+) . map (flip (,) 1)
-- `buildTree` builds a Huffman tree from a list of character frequencies
-- (obtained, for example, from `freqList` or elsewhere).
-- It sorts the list in ascending order by frequency, turns each (char, freq) pair
-- into a one-leaf tree and keeps merging two trees with the smallest frequencies
-- until only one tree is remaining.
buildTree :: [(Char, Int)] -> HTree
buildTree = bld . map (uncurry Leaf) . sortBy (compare `on` snd)
where bld (t:[]) = t
bld (a:b:cs) = bld $ insertBy (compare `on` weight) (merge a b) cs
-- The next function traverses a Huffman tree to obtain a list of codes for
-- all characters and converts this list into a `Map`.
buildCodemap :: Bits a => HTree -> Codemap a
buildCodemap = M.fromList . buildCodelist
where buildCodelist (Leaf c w) = [(c, [])]
buildCodelist (Fork l r w) = map (addBit zer) (buildCodelist l) ++ map (addBit one) (buildCodelist r)
where addBit b = second (b :)
-- Simple functions to get a Huffman tree or a `Codemap` from a `String`.
stringTree :: String -> HTree
stringTree = buildTree . freqList
stringCodemap :: Bits a => String -> Codemap a
stringCodemap = buildCodemap . stringTree
-- Time to do the real encoding and decoding!
-- Encoding function just represents each character of a string by corresponding
-- sequence of `Bit`s.
encode :: Bits a => Codemap a -> String -> [a]
encode m = concat . map (m M.!)
encode' :: Bits a => HTree -> String -> [a]
encode' t = encode $ buildCodemap t
-- Decoding is a little trickier. We have to traverse the tree until
-- we reach a leaf which means we've just finished reading a sequence
-- of `Bit`s corresponding to a single character.
-- We keep doing this to process the whole list of `Bit`s.
decode :: Bits a => HTree -> [a] -> String
decode tree = dcd tree
where dcd (Leaf c _) [] = [c]
dcd (Leaf c _) bs = c : dcd tree bs
dcd (Fork l r _) (b:bs) = dcd (if b == zer then l else r) bs
Output:
huffmancompress.hs:17:24: error:
* Ambiguous type variable `a0' arising from a use of `buildCodemap'
prevents the constraint `(Bits a0)' from being solved.
Relevant bindings include
codeMaphTest :: Codemap a0 (bound at huffmancompress.hs:17:9)
Probable fix: use a type annotation to specify what `a0' should be.
These potential instances exist:
instance Bits Bool -- Defined at huffmancompress.hs:35:10
instance Bits Int -- Defined at huffmancompress.hs:31:10
* In the expression: buildCodemap treeTest
In an equation for `codeMaphTest':
codeMaphTest = buildCodemap treeTest
In the expression:
do putStrLn "Start test"
let foo = "Hello World"
let freqTest = freqList foo
putStrLn "Frequentie list"
....
|
17 | let codeMaphTest = buildCodemap treeTest
| ^^^^^^^^^^^^^^^^^^^^^
I've tried serveral things I found on the internet but nothing worth mentioning to be honest.
Maybe any of you guys can help me out!
On line 17, where the error points you:
let codeMaphTest = buildCodemap treeTest
What type is codeMaphTest? Should it be Codemap Int? Or Codemap String? Or, perhaps, Codemap Bool? The function buildCodemap can return any type, as long as it has an instance of Bit. So what type should it be?
The compiler doesn't know. There is nowhere to glean this information from. It's ambiguous.
And this is exactly what the compiler is telling you: "ambiguous type variable".
One way to fix this is to provide a type annotation (exactly as the error message says, by the way):
let codeMaphTest :: Codemap Int = buildCodemap treeTest
Note that I chose Int just as an example, because I don't know which type you meant (I'm somewhat like the compiler in that respect). Please substitute your own type - the one you actually wanted there.
Your code is indeed ambiguous. buildCodemap treeTest has a polymorphic type Bits a => Codemap a, so it can be used as a Codemap Int, a Codemap Bool, or even as another type if you defines further instances of Bits.
This is not a problem, on its own, but later on you try to use this value (e.g., to print it), so we really need to pick a concrete type a.
You could pick a at the definition point:
let codeMaphTest :: Codemap Int
codeMaphTest = buildCodemap treeTest
Or, alternatively, you could choose a later on, where you use it
print (codeMaphTest :: Codemap Int)

Using FsCheck I get different results on tests, once 100% passed and the other time error

I created a generator to generate lists of int with the same lenght and to test the property of zip and unzip.
Running the test I get once in a while the error
Error: System.ArgumentException: list2 is 1 element shorter than list1
but it shouldn't happen because of my generator.
I got three times the test 100% passed and then the error above. Why?
It seems my generator is not working properly.
let samelength (x, y) =
List.length x = List.length y
let arbMyGen2 = Arb.filter samelength Arb.from<int list * int list>
type MyGenZ =
static member genZip() =
{
new Arbitrary<int list * int list>() with
override x.Generator = arbMyGen2 |> Arb.toGen
override x.Shrinker t = Seq.empty
}
let _ = Arb.register<MyGenZ>()
let pro_zip (xs: int list, ys: int list) =
(xs, ys) = List.unzip(List.zip xs ys)
|> Prop.collect (List.length xs = List.length ys)
do Check.Quick pro_zip
Your code, as written, works for me. So I'm not sure what exactly is wrong, but I can give you a few helpful (hopefully!) hints.
In the first instance, try not using the registrating mechanism, but instead using Prop.forAll, as follows:
let pro_zip =
Prop.forAll arbMyGen2 (fun (xs,ys) ->
(xs, ys) = List.unzip(List.zip xs ys)
|> Prop.collect (List.length xs))
do Check.Quick pro_zip
Note I've also changed your Prop.collect call to collect the length of the list(s), which gives somewhat more interesting output. In fact your property already checks that the lists are the same length (albeit implicitly) so the test will fail with a counterexample if they are not.
Arb.filter transforms an existing Arbitrary (i.e. generator and filter) to a new Arbitrary. In other words, arbMyGen2 has a shrinking function that'll work (i.e. only returns smaller pairs of lists that are of equal length), while in genZip() you throw the shrinker away. It would be fine to simply write
type MyGenZ =
static member genZip() = arbMyGen2
instead.

How should I model a type-safe index in Purescript?

In my application, I'd like to index sets of objects in a type-safe way using a structure similar to a relational database index. For example, I might want to index a set of User objects based on age and name:
import Data.Map as M
import Data.Set as S
type AgeNameIndex = M.Map Int (M.Map String (S.Set User))
Furthermore, I'd like to do operations like union and difference on indexes efficiently, e.g.:
let a = M.singleton 42 $ M.singleton "Bob" $ S.singleton $ User { ... }
b = M.singleton 42 $ M.singleton "Tim" $ S.singleton $ User { ... }
c = union a b -- contains both Bob and Tim
I've tried to model this as follows:
module Concelo.Index
( index
, union
, subtract
, lastValue
, subIndex ) where
import Prelude (($), (>>>), flip, Unit, unit, class Ord)
import Control.Monad ((>>=))
import Data.Map as M
import Data.Set as S
import Data.Maybe (Maybe(Nothing, Just), fromMaybe)
import Data.Tuple (Tuple(Tuple))
import Data.Foldable (foldl)
import Data.Monoid (mempty)
class Index index key value subindex where
isEmpty :: index -> Boolean
union :: index -> index -> index
subtract :: index -> index -> index
lastValue :: index -> Maybe value
subIndex :: key -> index -> subindex
instance mapIndex :: (Index subindex subkey value subsubindex) =>
Index (M.Map key subindex) key value subindex where
isEmpty = M.isEmpty
union small large =
foldl (m (Tuple k v) -> M.alter (combine v) k m) large (M.toList small)
where
combine v = case _ of
Just v' -> Just $ union v v'
Nothing -> Just v
subtract small large =
foldl (m (Tuple k v) -> M.alter (minus v) k m) large (M.toList small)
where
minus v = (_ >>= v' ->
let subindex = subtract v v' in
if isEmpty subindex then Nothing else Just subindex)
lastValue m = M.findMax m >>= (_.value >>> lastValue)
subIndex k m = fromMaybe mempty $ M.lookup k m
instance setIndex :: (Ord value) => Index (S.Set value) Unit value Unit where
isEmpty = S.isEmpty
union = S.union
subtract = flip S.difference
lastValue s = Nothing -- todo: S.findMax
subIndex _ _ = unit
index f = foldl (acc v -> union (f v) acc) mempty
However, the Purescript compiler doesn't like that:
Compiling Concelo.Index
Error found:
in module Concelo.Index
at /home/dicej/p/pssync/src/Concelo/Index.purs line 24, column 1 - line 44, column 49
No type class instance was found for
Concelo.Index.Index subindex0
t1
t2
t3
The instance head contains unknown type variables. Consider adding a type annotation.
in value declaration mapIndex
where subindex0 is a rigid type variable
t1 is an unknown type
t2 is an unknown type
t3 is an unknown type
See https://github.com/purescript/purescript/wiki/Error-Code-NoInstanceFound for more information,
or to contribute content related to this error.
My understanding of this message is that I haven't properly stated that map values in the mapIndex instance are themselves Index instances, but I don't know how to fix that. Where might I add a type annotation to make this compile? Or am I even on the right track given what I'm trying to do?
This is almost certainly because PureScript currently lacks functional dependencies (or type families) which makes this kind of information un-inferrable. There's a writeup of the issue here: https://github.com/purescript/purescript/issues/1580 - it is something we want to support.
There was a discussion about a case very similar to this today as it happens: https://github.com/purescript/purescript/issues/2235
Essentially, the problem here is that the functions of the class do not use all of the type variables, which means there's no way to propagate the information to the constraint for looking up a suitable instance.
I don't really have a suggestion for how to do what you're after here with things as they are, aside from avoiding the class and implementing it with specific types in mind.

Global variables in Haskell

I have this function:
map(\x -> l ++ [x]) "Show" where l = ""
I want the values of l to be saved at every step of the map function (e.g. I don't want to return ["S","h","o","w"], I want it to return ["S","Sh","Sho","Show"])
Can someone help me?
You're nearly there:
inits (x:xs) = map (\ys -> x:ys) ([]:inits xs)
inits [] = []
but note that you can rewrite (\ys -> x:ys) as (x:), which puts x at the front of each list it encounters, giving
inits (x:xs) = map (x:) ([]:inits xs)
inits [] = []
This works because map (x:) ([]:inits xs) gives you (x:[]) : map (x:) (inits xs), so everything in the list starts with x, and the first one is just [x]. That's true also of inits xs, so each gets one element longer.
There's a standard function
As usual, you're not the first to want this, which is why the function is defined already in Data.List. All you need to do is add
import Data.List
to the top of the program and you get inits predefined.
How is inits defined there?
Now if you look up hoogle for that, http://www.haskell.org/hoogle/?q=inits you can click through to find
inits :: [a] -> [[a]]
inits xs = [] : case xs of
[] -> []
x : xs' -> map (x :) (inits xs')
which is almost exactly the same idea, but in a case statement, which moves the pattern matching to be internal to the function.
Notice that this is slightly different to what you wanted, because you get a [] at the front of your answer, but you could use tail to get rid of that.
myinits = tail.inits
How can you find if there's already a function?
You wanted to turn a list into a list of lists. That should have type [a]->[[a]]. You can search for that on hoogle http://www.haskell.org/hoogle/?hoogle=[a]+-%3E+[[a]] and it's the top answer (more generally it might be lower down and you'd have to browse a bit.
This works for a lot of standard functions, since hoogle indexes all of base for a start.
Use scanl :
Prelude> scanl (\a c -> a++[c]) "" "Show"
["","S","Sh","Sho","Show"]
An efficient version:
Prelude> map reverse . scanl (flip (:)) [] $ "Show"
["","S","Sh","Sho","Show"]
Use Data.List.inits:
> tail $ inits "Show"
["S","Sh","Sho","Show"]
Just combine inits and tail functions from Prelude:
tail . inits $ "Show"

Is there a way to get a Curried form of the binary operators in SML/NJ?

For example, instead of
- op =;
val it = fn : ''a * ''a -> bool
I would rather have
- op =;
val it = fn : ''a -> ''a -> bool
for use in
val x = getX()
val l = getList()
val l' = if List.exists ((op =) x) l then l else x::l
Obviously I can do this on my own, for example,
val l' = if List.exists (fn y => x = y) l then l else x::l
but I want to make sure I'm not missing a more elegant way.
You could write a helper function that curries a function:
fun curry f x y = f (x, y)
Then you can do something like
val curried_equals = curry (op =)
val l' = if List.exists (curried_equals x) l then l else x::l
My knowledge of SML is scant, but I looked through the Ullman book and couldn't find an easy way to convert a function that accepts a tuple to a curried function. They have two different signatures and aren't directly compatible with one another.
I think you're going to have to roll your own.
Or switch to Haskell.
Edit: I've thought about it, and now know why one isn't the same as the other. In SML, nearly all of the functions you're used to actually accept only one parameter. It just so happens that most of the time you're actually passing it a tuple with more than one element. Still, a tuple is a single value and is treated as such by the function. You can't pass such function a partial tuple. It's either the whole tuple or nothing.
Any function that accepts more than one parameter is, by definition, curried. When you define a function that accepts multiple parameters (as opposed to a single tuple with multiple elements), you can partially apply it and use its return value as the argument to another function.