hspec - type issue in error assertion

Hello fellow Haskellers! I'm approaching learning the basics of Haskell by going through https://wiki.haskell.org/99_questions. At the same time I write tests for my code in Hspec. Consider question no. 2: "Find the last but one element of a list". My solution: -- Problem 02 myButLast :: [a] -> a myButLast [] = error "Empty list" myButLast [x] = error "List has only one element" myButLast [x1,x2] = x1 myButLast (x:xs) = myButLast xs and a a test: describe "02 myButLast" $ do it "returns the last but one element of a list" $ do myButLast [] `shouldThrow` anyErrorCall myButLast [1] `shouldThrow` anyErrorCall -- <- this line causes the problem myButLast [1..4] `shouldBe` 3 myButLast ['x','y','z'] `shouldBe` 'y' myButLast "abc" `shouldBe` 'b' Building tests with stack test command causes the below compilation error: • No instance for (Num (IO a0)) arising from the literal ‘1’
• In the expression: 1 In the first argument of ‘myButLast’, namely ‘[1]’ In the first argument of ‘shouldThrow’, namely ‘myButLast [1]’ | 27 | myButLast [1] `shouldThrow` anyErrorCall |
From what I understand, type of myButLast [1] is different than expected by shouldThrow. What I don't understand is why exactly it behaves so and how to fix this problem. Only that one assertion doesn't compile. The others are fine. Particularly, why does myButLast [] `shouldThrow` anyErrorCall work but with one element it doesn't?
Can you please give me a hand?

According to my guess:
1. shouldThrow receives `IO a` as a first argument.
https://www.stackage.org/haddock/lts-11.17/hspec-expectations-0.8.2/Test-Hsp...
2. So, both ` myButLast [] ` and ` myButLast [1] ` must be some `IO a`
3. Then, ` myButLast` 's type is inferred as `[IO a] -> IO a` when
given `[]`: the element of the list is `IO a` (Which actually would be `IO
()` by the default rule).
4. Similarly, ` myButLast [1] ` 's `a` (the type of the element of the
list) must be `IO something`. But any of `IO something` can't be a `Num`'s
instance (as the error message " No instance for (Num (IO a0)) arising
from the literal ‘1’ " says).
That's why ` myButLast [1] ` can't be compiled.
To fix it, use `evaluate
https://www.stackage.org/haddock/lts-11.17/base-4.10.1.0/Control-Exception.h...
`:
`evaluate myButLast [1]`
One more note: maybe you know we usually should not use `error`, which
raises an error in a pure function.
So, we usually handle errors in an `IO` context. That's why `shouldThrow`
receives an `IO a`.
2018年7月9日(月) 2:57 Paweł Bałaga
Hello fellow Haskellers!
I'm approaching learning the basics of Haskell by going through https://wiki.haskell.org/99_questions. At the same time I write tests for my code in Hspec. Consider question no. 2: "Find the last but one element of a list".
My solution: -- Problem 02 myButLast :: [a] -> a myButLast [] = error "Empty list" myButLast [x] = error "List has only one element" myButLast [x1,x2] = x1 myButLast (x:xs) = myButLast xs
and a a test: describe "02 myButLast" $ do it "returns the last but one element of a list" $ do myButLast [] `shouldThrow` anyErrorCall myButLast [1] `shouldThrow` anyErrorCall -- <- this line causes the problem myButLast [1..4] `shouldBe` 3 myButLast ['x','y','z'] `shouldBe` 'y' myButLast "abc" `shouldBe` 'b'
Building tests with stack test command causes the below compilation error:
• No instance for (Num (IO a0)) arising from the literal ‘1’
• In the expression: 1 In the first argument of ‘myButLast’, namely ‘[1]’ In the first argument of ‘shouldThrow’, namely ‘myButLast [1]’ | 27 | myButLast [1] `shouldThrow` anyErrorCall |
From what I understand, type of myButLast [1] is different than expected by shouldThrow. What I don't understand is why exactly it behaves so and how to fix this problem. Only that one assertion doesn't compile. The others are fine. Particularly, why does myButLast [] `shouldThrow` anyErrorCall work but with one element it doesn't?
Can you please give me a hand?
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- 山本悠滋 twitter: @igrep GitHub: https://github.com/igrep GitLab: https://gitlab.com/igrep Facebook: http://www.facebook.com/igrep Google+: https://plus.google.com/u/0/+YujiYamamoto_igrep
participants (2)
-
Paweł Bałaga
-
Yuji Yamamoto