This code will compile correctly:
import Text.Printf
import Test.HUnit
doubleMe x = x + x
doubleUs x y = doubleMe x + doubleMe y
doubleSmallNumber x = if x > 100 then x else x*2
doubleSmallNumber' x = if x > 100 then x else x*2 + 1
conanO'Brien = "It's a-me, Conan O'Brien!"
main = do
runTestTT $ TestList [TestCase $ ae 4 $ doubleMe 2,
TestCase $ ae 10 $ doubleUs 2 3,
TestCase $ ae 4 $ doubleSmallNumber 2,
TestCase $ ae 1000 $ doubleSmallNumber' 1000,
TestCase $ assertEqual "" "It's a-me, Conan O'Brien!" conanO'Brien]
where ae = assertEqual ""
The output is:
$ clear && ghc baby.hs && ./baby
[1 of 1] Compiling Main ( baby.hs, baby.o )
Linking baby ...
ld: warning: could not create compact unwind for .LFB3: non-standard register 5 being saved in prolog
Cases: 5 Tried: 5 Errors: 0 Failures: 0
When I change the code to:
import Text.Printf
import Test.HUnit
doubleMe x = x + x
doubleUs x y = doubleMe x + doubleMe y
doubleSmallNumber x = if x > 100 then x else x*2
doubleSmallNumber' x = if x > 100 then x else x*2 + 1
conanO'Brien = "It's a-me, Conan O'Brien!"
main = do
runTestTT $ TestList [TestCase $ ae 4 $ doubleMe 2,
TestCase $ ae 10 $ doubleUs 2 3,
TestCase $ ae 4 $ doubleSmallNumber 2,
TestCase $ ae 1000 $ doubleSmallNumber' 1000,
TestCase $ ae "It's a-me, Conan O'Brien!" conanO'Brien]
where ae = assertEqual ""
I get:
[1 of 1] Compiling Main ( baby.hs, baby.o )
baby.hs:12:65:
No instance for (Num [Char])
arising from the literal `1000'
Possible fix: add an instance declaration for (Num [Char])
In the first argument of `doubleSmallNumber'', namely `1000'
In the second argument of `($)', namely `doubleSmallNumber' 1000'
In the second argument of `($)', namely
`ae 1000 $ doubleSmallNumber' 1000'
I don't understand why.
Also does anybody have any ideas for fixing the ld warning:
ld: warning: could not create compact unwind for .LFB3: non-standard register 5 being saved in prolog
This is an example of the monomorphism restriction. ae
"looks like a value" (doesn't have arguments) and doesn't have an explicit type, so compiler won't infer a polymorphic type for it.
In first example, it gets type Int -> Int -> Assertion
(I think).
In the second, from ae "It's a-me, Conan O'Brien!" conanO'Brien
it gets the type String -> String -> Assertion
. Remember that the type of integer literals is actually Num a => a
, and 1000
gets type String
from ae
, so the compiler needs an instance Num String
.
EDITED: This can be fixed by giving an explicit type annotation: where ae :: (Show a, Eq a) => a -> a -> Assertion = assertEqual ""
. Or by adding arguments to definition (eta-expanding it): where ae x y = assertEqual "" x y
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With