test1 = hspec $ do
describe "blabla" $ do
it "should be equl" $ verbose $
\input-> ...
In the above code, when a test failed, it prints the failed input. But I'm actually interested in another value that can be calculated from input. Can I ask QuickCheck to print the other value?
Somehow I've never seen it advertised, but you can use hspecs expectations inside of QuickCheck properties. Here is an example:
describe "blabla" $ do
it "should be equl" $ verbose $ \input ->
round input `shouldBe` floor (input :: Double)
Above property is clearly not true, so it should fail. Since we are not only interested input, but also want to know the computed values from it, shouldBe will give us just that:
3) blabla should be equl
Falsifiable (after 2 tests and 4 shrinks):
0.6
expected: 0
but got: 1
Naturally, due to verbose, only input will be printed for passing tests, while computed value (eg. round input) will only be printed for a failed test case, which is what you were looking for it seems anyways.
Related
First, I don't have an easy to reproduce example on hand, as the code is calling out to a MATLAB engine, which requires a license. It may be possible to construct a similar example, just using C, though. I have the following snippet from a test:
ei1 :: Either SomeException MAnyArray <- try $ engineGetVar eng foopi
putStrLn $ assert (isRight ei1) " Can clearVar once"
clearVar eng foopi
ei2 :: Either SomeException MAnyArray <- try $ engineGetVar eng foopi
putStrLn $ assert (isLeft ei2) $
" Can't clearVar twice: " <> (show $ lefts [ei2])
putStrLn " Finished testClearVar"
This results in the output:
Can clearVar once
Error using save
Variable 'foopi' not found.
Can't clearVar twice: []
Finished testClearVar
The confusing bit is this expression, since the assertion appears to succeed (meaning that ei2 is a Left value, but when calling lefts [ei2], no Left values are found):
putStrLn $ assert (isLeft ei2) $
" Can't clearVar twice: " <> (show $ lefts [ei2])
If you look closely at documentation of assert you will find:
Assertions can normally be turned on or off with a compiler flag (for GHC, assertions are normally on unless optimisation is turned on with -O or the -fignore-asserts option is given). When assertions are turned off, the first argument to assert is ignored, and the second argument is returned as the result.
I assume this is a regular package you are working on and not just a file you are compiling manually with ghc. By default cabal will compile a project with -O, which means your asserts are simply ignored. What you need is either -O0 or -fno-ignore-asserts flag added. But what I would recommend is just don't rely on assert at all.
I'm doing some very simple performance testing of a simple function that I believe has O(n)(squared) performance (or worse).
Currently I'm running multiple statements which is tedious to repeat:
ghci> myfunction 0 100
true
ghci> myfunciton 0 200
true
ghci> myfunction 0 300
true
ghci> :r
Is there a way I can run all four GHCi statements? I can't just combine them using "native" Haskell as I'd like to include the :r (which is a GHCi statement - not exactly Haskell) that gets run at the end.
One way I've found is creating a separate file:
myfunction 0 100
myfunction 0 200
myfunction 0 300
:r
and then using:
:script path/to/file
You can define a custom GHCi command using :def in this way:
> :def foo (\_ -> return "print 100\nprint 200\n:t length")
> :foo
100
200
length :: Foldable t => t a -> Int
In the returned string, :-commands can be included as well, like :t above.
One way of doing it is to create a testing suite in your Cabal file in which you place your function calls as tests, then use stack test --file-watch. That recompiles and reruns the tests every time you save a file.
I am trying to use hint package from hackage to create a simple environment where user can issue lines of code for evaluation (like in ghci). I expect some of the input lines to be erroneous (eval would end the session with an error). How can I create a robust session that ignores erroneous input (or better: it reports an error but can accept other input) and keeps the previously consistent state?
Also, I would like to use it in do style, i.e. let a = 3 as standalone input line makes sense.
To clarify things: I have no problem with a single eval. What I would like to do, is allow continuing evaluation even after some step failed. Also I would like to incrementally extend a monadic chain (as you do in ghci I guess).
In other words: I want something like this, except that I get to evaluate 3 and don't stop at undefined with the error.
runInterpreter $ setImports [ "Prelude" ] >> eval "undefined" >> eval "3"
More specifically I would like something like this to be possible:
runInterpreter $ setImports ... >> eval' "let a = (1, 2)" -- modifying context
>> typeOf "b" -- error but not breaking the chain
>> typeOf "a" -- (Num a, Num b) => (a, b)
I don't expect it to work this straightforwardly, this is just to show the idea. I basically would like to build up some context (as you do in ghci) and every addition to the context would modify it only if there is no failure, failures could be logged or explicitly retrieved after each attempt to modify the context.
You didn't show any code so I don't know the problem. The most straight-forward way I use hint handles errors fine:
import Language.Haskell.Interpreter
let doEval s = runInterpreter $ setImports ["Prelude"] >> eval s
has resulted in fine output for me...
Prelude Language.Haskell.Interpreter> doEval "1 + 2"
Right "3"
Prelude Language.Haskell.Interpreter> doEval "1 + 'c'"
ghc: panic! (the 'impossible' happened)
(GHC version 7.10.2 for x86_64-apple-darwin):
nameModule doEval_a43r
... Except that now the impossible happens... that's a bug. Notice you are supposed to get Left someError in cases like these:
data InterpreterError
= UnknownError String
| WontCompile [GhcError]
| NotAllowed String
| GhcException String
-- Defined in ‘hint-0.4.2.3:Hint.Base’
Have you looked through the ghchq bug list and/or submitted an issue?
EDIT:
And the correct functionality is back, at least as of GHC 7.10.3 x64 on OS X with hint version 0.4.2.3. In other words, it appears the bug went away from 7.10.2 to 7.10.3
The output is:
Left (WontCompile [GhcError {errMsg = ":3:3:\n No instance for (Num Char) arising from a use of \8216+\8217\n In the expression: 1 + 'c'\n In an equation for \8216e_11\8217: e_11 = 1 + 'c'\n In the first argument of \8216show_M439719814875238119360034\8217, namely\n \8216(let e_11 = 1 + 'c' in e_11)\8217"}])
Though executing the doEval line twice in GHCi does cause a panic, things seem to work once in the interpreter and properly regardless when compiled.
Why is the function name repeated in
example:
lucky :: (Integral a) => a -> String
lucky 7 = "LUCKY NUMBER SEVEN!"
lucky x = "Sorry, you're out of luck, pal!"
when should I not be repeating function name? what is the meaning of it?
thanks
What you are seeing is pattern match in action.
I will show you another example:
test 1 = "one"
test 2 = "two"
test 3 = "three"
Demo in ghci:
ghci> test 1
"one"
ghci> test 2
"two"
ghci> test 3
"three"
ghci> test 4
"*** Exception: Non-exhaustive patterns in function test
So, when you call any function, the runtime system will try to match
the input with the defined function. So a call to test 3 will
initially check test 1 and since 1 is not equal to 3, it will
move on to the next definition. Again since 2 is not equal to 3,
it will move to the next defintion. In the next definiton since 3 is
equal to 3 it will return "three" String back. When you try to
pattern match something, which doesn't exist at all, the program
throws the exception.
This kind of pattern matching can be transformed to a case statement (and indeed, that's what compilers will normally do!):
lucky' n = case n of
7 -> "LUCKY NUMBER SEVEN!"
x -> "Sorry, you're out of luck, pal!"
Because the x isn't really used, you'd normally write _ -> "Sorry, ..." instead.
Note that this is not2 the same as
lucky'' n = if n==7 then ...
Equality comparison with (==) is in general more expensive1 than pattern matching, and also comes out uglier.
1 Why it's more expensive: suppose we have a big data structure. To determine that they are equal, the program will need to dig through both entire structures, make sure really all branches are equal. However, if you pattern match, you will just compare a small part you're interested in right now.
2 Actually, it is the same in the case, but just because the compiler has a particular trick for pattern matching on numbers: it rewrites it with (==). This is really special for Num types and not true for anything else. (Except if you use the OverloadedStrings extension.)
That definition of lucky uses "pattern matching", and equals (in this case)
lucky :: (Integral a) => a -> String
lucky a = if a == 7
then "LUCKY NUMBER SEVEN!"
else "Sorry, you're out of luck, pal!"
I assume you're looking at learn you a haskell. After that example, it says that
When you call lucky, the patterns will be checked from top to bottom and when it conforms to a pattern, the corresponding function body will be used.
So the first line indicates the type of the function, and later lines are patterns to check. Each line has the function name so the compiler knows you're still talking about the same function.
Think of it this way: When you write the expression lucky (a+b) or whatever, the compiler will attempt to replace lucky (a+b) with the first thing before the = in the function definition that "fits." So if a=3 and b=4, you get this series of replacements:
lucky (a+b) =
lucky (3+4) =
--pattern matching occurs...
lucky 7 =
"LUCKY NUMBER SEVEN!"
This is part of what makes Haskell so easy to reason about in practice; you get a system that works similarly to math.
I just started with Haskell and tried to do write some tests first. Basically, I want to define some function and than call this function to check the behavior.
add :: Integer -> Integer -> Integer
add a b = a+b
-- Test my function
add 2 3
If I load that little script in Hugs98, I get the following error:
Syntax error in declaration (unexpected `}', possibly due to bad layout)
If I remove the last line, load the script and then type in "add 2 3" in the hugs interpreter, it works just fine.
So the question is: How can I put calls of my functions in the same script as the function definition? I just want to load the script and be able to check if it does what I expect it to...I don't want to type them in manually all the time.
Others have said how to solve your immediate problem, but for testing you should be using QuickCheck or some other automated testing library.
import Test.QuickCheck
prop_5 = add 2 3 == 5
prop_leftIdentity n = add 0 n == n
Then run quickCheck prop_5 and quickCheck prop_leftIdentity in your Hugs session. QuickCheck can do a lot more than this, but that will get you started.
(Here's a QuickCheck tutorial but it's out of date. Anyone know of one that covers QuickCheck 2?)
the most beginner friendly way is probably the doctest module.
Download it with "cabal install doctest", then put your code into a file "Add.hs" and run "doctest Add.hs" from the command line.
Your code should look like this, the formatting is important:
module Add where
-- | add adds two numbers
--
-- >>> add 2 3
-- 5
-- >>> add 5 0
-- 5
-- >>> add 0 0
-- 0
add :: Integer -> Integer -> Integer
add a b = a+b
HTH Chris
Make a top level definition:
add :: Integer -> Integer -> Integer
add a b = a + b
test1 = add 2 3
Then call test1 in your Hugs session.
How can I put calls of my functions in the same script as the function definition? I just want to load the script and be able to check if it does what I expect it to...I don't want to type them in manually all the time.
In short, you can't. Wrap it in a function and call it instead. Your file serves as a valid Haskell module, and having "flying" expression is not a valid way to write it.
You seem to come from a scripting language background, but don't try treating Haskell as one of them.
If you have ghc installed, then the runhaskell command will interpret and run the main function in your file.
add x y = x + y
main = print $ add 2 3
Then on the command line
> runhaskell Add.hs
5
Not sure, but hugs probably has a similar feature to the runhaskell command. Or, if you load the file into the hugs interpreter, you can simply run it by calling main.
I was trying to do the same thing and I just made a function that ran through all my test cases (using guards) and returned 1 if they all passed and threw an error if any failed.
test :: Num b => a->b
test x
| sumALL [1] /= 1 = error "test failed"
| sumALL [0,1,2] /= 3 = error "test failed"
...
| otherwise = 1