I'm trying to set up a series of tests for a simple tic tac toe program I've written in Haskell and I'm unable to get past my first test due to a strange error being thrown reading:
Tests.hs:11:61: error:
* Couldn't match expected type `Int' with actual type `IO Int'
* In the third argument of `assertEqual', namely
`(test_user_value x)'
In the first argument of `TestCase', namely
`(assertEqual "for (test_user_value 3)," f (test_user_value x))'
In the expression:
TestCase
(assertEqual "for (test_user_value 3)," f (test_user_value x))
|
11 | test1 = TestCase (assertEqual "for (test_user_value 3)," f (test_user_value x))
| ^^^^^^^^^^^^^^^^^
Failed, one module loaded.
The value 'x' is an int but Haskell is reading it as 'IO Int' which is wrong, as I've specified "x :: Int". The function being tested has already been specified as "test_user_value :: Int -> IO Int" so I'm unsure why it is interpreting the variable incorrectly. Any suggestions would be appreciated.
It's not actually complaining about x
, it's complaining about the expression test_user_value x
- note that it is this expression that is underlined in the error message.
Since, as you have indicated, test_user_value :: Int -> IO Int
and x :: Int
, it follows that test_user_value x :: IO Int
- and that's exactly what the compiler tells you shouldn't be there. It's expecting an Int
, but you gave it IO Int
.
You can get an Int
out of it though. To do that, I think the do
notation would be the clearest:
test1 = TestCase $ do
v <- test_user_value x
assertEqual "for (test_user_value 3)," f v
Or you could write it a bit shorter using the =<<
operator:
test1 = TestCase (assertEqual "for (test_user_value 3)," f =<< test_user_value x)