[Haskell-cafe] hspec - type issue in error assertion

Yuji Yamamoto whosekiteneverfly at gmail.com
Sun Jul 8 23:06:55 UTC 2018


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-Hspec-Expectations.html#v:shouldThrow>
   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.html#v:evaluate>
`:
`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 <ppbalaga at gmail.com>:

> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20180709/bf49bd1e/attachment.html>


More information about the Haskell-Cafe mailing list