How do I test for an error in Haskell? - unit-testing

I want to be able to make sure a function will throw an error when it receives and invalid value. For example, let says I have a function pos that only returns a positive number:
pos :: Int -> Int
pos x
| x >= 0 = x
| otherwise = error "Invalid Input"
This is a simplistic example, but I hope you get the idea.
I want to be able to write a test case that will expect an error and consider it a passing test. For example:
tests = [pos 1 == 1, assertError pos (-1), pos 2 == 2, assertError pos (-2)]
runTests = all (== True) tests
[My Solution]
This is what I ended up going with based on #hammar's comment.
instance Eq ErrorCall where
x == y = (show x) == (show y)
assertException :: (Exception e, Eq e) => e -> IO a -> IO ()
assertException ex action =
handleJust isWanted (const $ return ()) $ do
action
assertFailure $ "Expected exception: " ++ show ex
where isWanted = guard . (== ex)
assertError ex f =
TestCase $ assertException (ErrorCall ex) $ evaluate f
tests = TestList [ (pos 0) ~?= 0
, (pos 1) ~?= 1
, assertError "Invalid Input" (pos (-1))
]
main = runTestTT tests

OP's solution defines assertException, but it looks like Test.HUnit.Tools.assertRaises from testpack is also usable here.
I added the msg argument to assertError to match how assertRaises works, and included selective imports so noobs like me can learn where commonly used things are imported from.
import Control.Exception (ErrorCall(ErrorCall), evaluate)
import Test.HUnit.Base ((~?=), Test(TestCase, TestList))
import Test.HUnit.Text (runTestTT)
import Test.HUnit.Tools (assertRaises)
pos :: Int -> Int
pos x
| x >= 0 = x
| otherwise = error "Invalid Input"
instance Eq ErrorCall where
x == y = (show x) == (show y)
assertError msg ex f =
TestCase $ assertRaises msg (ErrorCall ex) $ evaluate f
tests = TestList [
(pos 0) ~?= 0
, (pos 1) ~?= 1
, assertError "Negative argument raises an error" "Invalid Input" (pos (-1))
]
main = runTestTT tests

There are several ways to handle errors in Haskell. Here is an overview: http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors
[Edit]
The first example shows how to catch errors, e.g.
half :: Int -> Int
half x = if even x then x `div` 2 else error "odd"
main = do catch (print $ half 23) (\err -> print err)
That said, this kind of error handling is better suited for IO stuff, in pure code like yours Maybe, Either or something similar is usually a better choice. It could be as simple as...
pos :: Int -> Maybe Int
pos x
| x >= 0 = Just x
| otherwise = Nothing
tests = [pos 1 == Just 1
,pos (-1) == Nothing
,pos 2 == Just 2
,pos (-2) == Nothing
]
main = print $ and tests
... if you don't need an error type.

Related

Ocaml :This expression has type bool but an expression was expected of type unit

I got some issue with my code I don't understand. Why did I get this error: This expression has type bool but an expression was expected of type unit. Here is the code
let well_formed (_dimension : int) (_initial1 : _ list)
(_initial2 : _ list) : bool =
if List.length _initial1 + List.length _initial2 != 4 * _dimension then false
else if List.length _initial1 != List.length _initial2 then false
else
let c = 0 in
for i = 1 to _dimension do
let liste =
List.filter (fun x -> x == i) _initial1
# List.filter (fun x -> x == i) _initial2
in
if List.length liste == 4 then c = c + 1 else c = c
done;
if c == _dimension then true else false
I reformated your code, actually for loop have no impact on your code.
let well_formed dimension initial1 initial2 =
let ll1 = List.length initial1 in
let ll2 = List.length initial2 in
let total_list_length = ll1 + ll2 in
if total_list_length != (4 * dimension) then false else
if ll1 != ll2 then false else
let c = 0 in
(* this code do nothing : what is expected ?
for i = 1 to dimension do
let liste = (List.filter(fun x -> x == i) initial1 )#(List.filter(fun x->x == i) initial2) in
if ( List.length liste ) == 4 then c = c+1 else c = c
done;
*)
if c == dimension then true else false
You need to learn imperative features of ocaml if you want to write code this way.
For example c = c + 1 return false
if you want to increment a variable you need to create a ref variable.
OCaml is not C/Python/Javascript, in particular
x = x + 1
means the same as
x == x + 1
in C or Python, i.e., it is a comparison operator. The == operator is the physical comparison (the same as === in Javascript).
Also, integers in OCaml are immutable, so if you want to have a mutable number you need to wrap it in a reference and use := for assignment, e.g.,
let x = ref 0 in
for i = 0 to 5 do
x := !x + 2
done

if statement in do block gives error message [duplicate]

This question already has answers here:
Parse error on input 'if' when trying to use a condition inside a do block
(3 answers)
Closed 3 years ago.
I'm trying to make a very simple snake-like game where, if you try to go to a x,y coordinate you have already visited, you lose the game.
This is code that's working so far (you can move player 1 with arrowkeys and player 2 with wasd):
import UI.NCurses
main :: IO ()
main = runCurses $ do
w <- defaultWindow
updateWindow w $ do
drawBorder Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
render
loop w [] 1 1 0 0 10 10 0 0
loop :: Window -> [(Integer, Integer)] -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Integer -> Curses ()
loop w list p1x p1y p1oldDx p1oldDy p2x p2y p2oldDx p2oldDy = do
e <- getEvent w (Just 100)
let coordList = updateXY e p1oldDx p1oldDy p2oldDx p2oldDy
let p1dX = coordList !! 0
let p1dY = coordList !! 1
let p2dX = coordList !! 2
let p2dY = coordList !! 3
updateWindow w $ do
moveCursor (p1y+p1dY) (p1x+p1dX)
drawString ("#")
moveCursor (p2y+p2dY) (p2x+p2dX)
drawString ("#")
render
let updatedList = list ++ [(p1y+p1dY, p1x+p1dX)] ++ [(p2y+p2dY, p2x+p2dX)]
loop w updatedList (p1x+p1dX) (p1y+p1dY) p1dX p1dY (p2x+p2dX) (p2y+p2dY) p2dX p2dY
updateXY :: Maybe Event -> Integer -> Integer -> Integer -> Integer -> [Integer]
updateXY e p1oldX p1oldY p2oldX p2oldY
| e == Just (EventSpecialKey KeyLeftArrow) = [-1, 0, p2oldX, p2oldY]
| e == Just (EventSpecialKey KeyRightArrow) = [1, 0, p2oldX, p2oldY]
| e == Just (EventSpecialKey KeyDownArrow) = [0, 1, p2oldX, p2oldY]
| e == Just (EventSpecialKey KeyUpArrow) = [0, -1, p2oldX, p2oldY]
| e == Just (EventCharacter 'a') = [p1oldX, p1oldY, -1, 0]
| e == Just (EventCharacter 'd') = [p1oldX, p1oldY, 1, 0]
| e == Just (EventCharacter 's') = [p1oldX, p1oldY, 0, 1]
| e == Just (EventCharacter 'w') = [p1oldX, p1oldY, 0, -1]
| p1oldX /= 0 = [p1oldX, 0, p2oldX, p2oldY]
| p1oldY /= 0 = [0, p1oldY, p2oldX, p2oldY]
| p2oldX /= 0 = [p1oldX, p1oldY, p2oldX, 0]
| p2oldY /= 0 = [p1oldX, p1oldY, 0, p2oldY]
| otherwise = [1, 0, 1, 0] -- Starts moving in x-direction. Change to (0,0) for stand-still
So as you move, "#" characters are put down. The above code does nothing if you go to a coordinate which already has a "#" on it, so I tried changing the loop function by adding this just before the let updatedList...:
if length (filter (==(p1x, p1y)) list) > 0 then gameOver w "player one lost"
if length (filter (==(p2x, p2y)) list) > 0 then gameOver w "player two lost"
And adding a temporary gameOver function:
gameOver w player =
updateWindow w $ do
moveCursor (10) (10)
drawString (player)
render
But when I try to load this file in GHCI I get the following error message:
parse error on input 'if'
ifs need elses. Period. You can use the when function for when you need the imperative style "if this, then do that, else do nothing," but there is no built-in syntax:
import Control.Monad
when (length (filter (==(p1x, p1y)) list) > 0) $ gameOver w "player one lost"
when (length (filter (==(p2x, p2y)) list) > 0) $ gameOver w "player two lost"
The definition of when is
when cond action = if cond then action else pure ()
In Haskell, if expressions must have both then and else clauses.
Without the else, you get the error.
Both the consequent and the alternative clause must have the same type.

F# Performance: What is making this code so slow?

This F# code is an attempt to solve Project Euler problem #58:
let inc = function
| n -> n + 1
let is_prime = function
| 2 -> true
| n when n < 2 || n%2=0-> false
| n ->
[3..2..(int (sqrt (float n)))]
|> List.tryFind (fun i -> n%i=0)
|> Option.isNone
let spir = Seq.initInfinite (fun i ->
let n = i%4
let a = 2 * (i/4 + 1)
(a*n) + a + (a-1)*(a-1))
let rec accum se p n =
match se with
| x when p*10 < n && p <> 0 -> 2*(n/4) + 1
| x when is_prime (Seq.head x) -> accum (Seq.tail x) (inc p) (inc n)
| x -> accum (Seq.tail x) p (inc n)
| _ -> 0
printfn "%d" (accum spir 0 1)
I do not know the running time of this program because I refused to wait for it to finish. Instead, I wrote this code imperatively in C++:
#include "stdafx.h"
#include "math.h"
#include <iostream>
using namespace std;
int is_prime(int n)
{
if (n % 2 == 0) return 0;
for (int i = 3; i <= sqrt(n); i+=2)
{
if (n%i == 0)
{
return 0;
}
}
return 1;
}
int spir(int i)
{
int n = i % 4;
int a = 2 * (i / 4 + 1);
return (a*n) + a + ((a - 1)*(a - 1));
}
int main()
{
int n = 1, p = 0, i = 0;
cout << "start" << endl;
while (p*10 >= n || p == 0)
{
p += is_prime(spir(i));
n++; i++;
}
cout << 2*(i/4) + 1;
return 0;
}
The above code runs in less than 2 seconds and gets the correct answer.
What is making the F# code run so slowly? Even after using some of the profiling tools mentioned in an old Stackoverflow post, I still cannot figure out what expensive operations are happening.
Edit #1
With rmunn's post, I was able to come up with a different implementation that gets the answer in a little under 30 seconds:
let inc = function
| n -> n + 1
let is_prime = function
| 2 -> true
| n when n < 2 || n%2=0-> false
| n ->
[3..2..(int (sqrt (float n)))]
|> List.tryFind (fun i -> n%i=0)
|> Option.isNone
let spir2 =
List.unfold (fun state ->
let p = fst state
let i = snd state
let n = i%4
let a = 2 * (i/4 + 1)
let diag = (a*n) + a + (a-1)*(a-1)
if p*10 < (i+1) && p <> 0 then
printfn "%d" (2*((i+1)/4) + 1)
None
elif is_prime diag then
Some(diag, (inc p, inc i))
else Some(diag, (p, inc i))) (0, 0)
Edit #2
With FuleSnabel's informative post, his is_prime function makes the above code run in under a tenth of a second, making it faster than the C++ code:
let inc = function
| n -> n + 1
let is_prime = function
| 1 -> false
| 2 -> true
| v when v % 2 = 0 -> false
| v ->
let stop = v |> float |> sqrt |> int
let rec loop vv =
if vv <= stop then
if (v % vv) <> 0 then
loop (vv + 2)
else
false
else
true
loop 3
let spir2 =
List.unfold (fun state ->
let p = fst state
let i = snd state
let n = i%4
let a = 2 * (i/4 + 1)
let diag = (a*n) + a + (a-1)*(a-1)
if p*10 < (i+1) && p <> 0 then
printfn "%d" (2*((i+1)/4) + 1)
None
elif i <> 3 && is_prime diag then
Some(diag, (inc p, inc i))
else Some(diag, (p, inc i))) (0, 0)
There is no Seq.tail function in the core F# library (UPDATE: Yes there is, see comments), so I assume you're using the Seq.tail function from FSharpx.Collections. If you're using a different implementation of Seq.tail, it's probably similar -- and it's almost certainly the cause of your problems, because it's not O(1) like you think it is. Getting the tail of a List is O(1) because of how List is implemented (as a series of cons cells). But getting the tail of a Seq ends up creating a brand new Seq from the original enumerable, discarding one item from it, and returning the rest of its items. When you go through your accum loop a second time, you call Seq.tail on that "skip 1 then return" seq. So now you have a Seq which I'll call S2, which asks S1 for an IEnumerable, skips the first item of S1, and returns the rest of it. S1, when asked for its first item, asks S0 (the original Seq) for an enumerable, skips its first item, then returns the rest of it. So for S2 to skip two items, it had to create two seqs. Now on your next run through when you ask for the Seq.tail of S2, you create S3 that asks S2 for an IEnumerable, which asks S1 for an IEnumerable, which asks S0 for an IEnumerable... and so on. This is effectively O(N^2), when you thought you were writing an O(N) operation.
I'm afraid I don't have time right now to figure out a solution for you; using List.tail won't help since you need an infinite sequence. But perhaps just knowing about the Seq.tail gotcha is enough to get you started, so I'll post this answer now even though it's not complete.
If you need more help, comment on this answer and I'll come back to it when I have time -- but that might not be for several days, so hopefully others will also answer your question.
Writing performant F# is very possible but requires some knowledge of patterns that have high relative CPU cost in a tight loop. I recommend using tools like ILSpy to find hidden overhead.
For instance one could imagine F# exands this expression into an effective for loop:
[3..2..(int (sqrt (float n)))]
|> List.tryFind (fun i -> n%i=0)
|> Option.isNone
However it currently doesn't. Instead it creates a List that spans the range using intrinsic operators and passes that to List.tryFind. This is expensive when compared to the actual work we like to do (the modulus operation). ILSpy decompiles the code above into something like this:
public static bool is_prime(int _arg1)
{
switch (_arg1)
{
case 2:
return true;
default:
return _arg1 >= 2 && _arg1 % 2 != 0 && ListModule.TryFind<int>(new Program.Original.is_prime#10(_arg1), SeqModule.ToList<int>(Operators.CreateSequence<int>(Operators.OperatorIntrinsics.RangeInt32(3, 2, (int)Math.Sqrt((double)_arg1))))) == null;
}
}
These operators aren't as performant as they could be (AFAIK this is currently being improved) but no matter how effecient allocating a List and then search it won't beat a for loop.
This means the is_prime is not as effective as it could be. Instead one could do something like this:
let is_prime = function
| 1 -> false
| 2 -> true
| v when v % 2 = 0 -> false
| v ->
let stop = v |> float |> sqrt |> int
let rec loop vv =
if vv <= stop then
(v % vv) <> 0 && loop (vv + 2)
else
true
loop 3
This version of is_prime relies on tail call optimization in F# to expand the loop into an efficient for loop (you can see this using ILSpy). ILSpy decompile the loop into something like this:
while (vv <= stop)
{
if (_arg1 % vv == 0)
{
return false;
}
int arg_13_0 = _arg1;
int arg_11_0 = stop;
vv += 2;
stop = arg_11_0;
_arg1 = arg_13_0;
}
This loop doesn't allocate memory and is just a rather efficient loop. One see some non-sensical assignments but hopefully the JIT:er eliminate those. I am sure is_prime can be improved even further.
When using Seq in performant code one have to keep in mind it's lazy and it doesn't use memoization by default (see Seq.cache). Therefore one might easily end up doing the same work over and over again (see #rmunn answer).
In addition Seq isn't especially effective because of how IEnumerable/IEnumerator are designed. Better options are for instance Nessos Streams (available on nuget).
In case you are interested I did a quick implementation that relies on a simple Push Stream which seems decently performant:
// Receiver<'T> is a callback that receives a value.
// Returns true if it wants more values, false otherwise.
type Receiver<'T> = 'T -> bool
// Stream<'T> is function that accepts a Receiver<'T>
// This means Stream<'T> is a push stream (as opposed to Seq that uses pull)
type Stream<'T> = Receiver<'T> -> unit
// is_prime returns true if the input is prime, false otherwise
let is_prime = function
| 1 -> false
| 2 -> true
| v when v % 2 = 0 -> false
| v ->
let stop = v |> float |> sqrt |> int
let rec loop vv =
if vv <= stop then
(v % vv) <> 0 && loop (vv + 2)
else
true
loop 3
// tryFind looks for the first value in the input stream for f v = true.
// If found tryFind returns Some v, None otherwise
let tryFind f (s : Stream<'T>) : 'T option =
let res = ref None
s (fun v -> if f v then res := Some v; false else true)
!res
// diagonals generates a tuple stream of all diagonal values
// The first value is the side length, the second value is the diagonal value
let diagonals : Stream<int*int> =
fun r ->
let rec loop side v =
let step = side - 1
if r (side, v + 1*step) && r (side, v + 2*step) && r (side, v + 3*step) && r (side, v + 4*step) then
loop (side + 2) (v + 4*step)
if r (1, 1) then loop 3 1
// ratio computes the streaming ratio for f v = true
let ratio f (s : Stream<'T>) : Stream<float*'T> =
fun r ->
let inc r = r := !r + 1.
let acc = ref 0.
let count = ref 0.
s (fun v -> (inc count; if f v then inc acc); r (!acc/(!count), v))
let result =
diagonals
|> ratio (snd >> is_prime)
|> tryFind (fun (r, (_, v)) -> v > 1 && r < 0.1)

What does val it = () : unit mean in SML?

I've never programmed in SML before, and I'm using SML/NJ. It keeps giving me the following at the end of each program I run:
val it = () : unit
What does this mean? Is it something I'm doing wrong?
it is the name of the result returned by your code. () : unit is a trivial placeholder value returned from things that are side-effect based.
It's more obvious when you enter something that's more commonly an expression at the prompt, e.g...
- 2 * 7;
val it = 14 : int
You can also use it for the side effect of printing things out:
fun printpos n =
if n <= 0 then (print "not positive!\n")
else (print (Int.toString n); print "\n");
printpos ~1;
printpos 1;
(* Output:
val printpos = fn : int -> unit
not positive!
val it = () : unit
1
val it = () : unit
*)

Why is this OCaml code receiving "Unexpected token"?

let rec move_robot (pos: int) (dir: string) (num_moves: int) : int =
let new_forward_position = pos + num_moves in
if (new_forward_position > 99) then failwith "cannot move beyond 99 steps"
else new_forward_position
let new_backward_position = pos - num_moves in
if (new_backward_position pos < 0) then failwith "cannot move less than 0 steps"
else new_backward_position
begin match dir with
| "forward" -> new_forward position
| "backward" -> new_backward_position
end
I keep on getting "unexpected token in" for the let new_backward_position line. What is my error?
Here is a code that compiles:
let rec move_robot pos dir num_moves =
let new_forward_position = pos + num_moves in
if new_forward_position > 99 then failwith "cannot move beyond 99 steps";
let new_backward_position = pos - num_moves in
if new_backward_position < 0 then failwith "cannot move less than 0 steps";
begin match dir with
| "forward" -> new_forward_position
| "backward" -> new_backward_position
end
I modified several things:
Important: if foo then bar else qux is an expression in OCaml, which takes either the value bar or qux. Thus bar and qux needs to have the same type.
new_backward_position instead of new_backward_position pos
you don't need type annotations : OCaml has type inference
no need for parentheses around the if clause
typo in new_forward position
Also, with your code's logic, let _ = move_robot 0 "forward" 5 fails. Shouldn't it return 5 instead? I suggest you define a sum type for pos and do a pattern matching on it first.
Your code has this basic structure if you assume the failures won't happen:
let f () =
let p = 3 in p
let q = 5 in q
...
It's not clear what you're trying to do, but this isn't well formed OCaml (as the compiler tells you). Maybe want you want is something more like this:
let f () =
let p = 3 in
let q = 5 in
match ...
If so, you need to move your ifs before your ins:
let f () =
let p = if badp then failwith "" else 3 in
let q = if badq then failwith "" else 5 in
match ...
Or maybe this is more what you want:
let f () =
let p = 3 in
let () = if badp p then failwith "" in
let q = 5 in
let () = if badq q then failwith "" in
match ...
(I hope this is helpful.)