No instance for (Show a0) arising from a use of ‘shouldBe’

1.2k views Asked by At

I'm new to haskell and I'm trying to learn hspec at the same time.

module ExercisesSpec where

import Test.Hspec
import Test.QuickCheck
import Control.Exception (evaluate)


halve :: [a] -> ([a], [a])
halve xs = splitAt (length xs `div` 2) xs

main :: IO ()
main = hspec $ do
  describe "halve" $ do
    it "0 elements" $ do
      halve [] `shouldBe` ([],[])

    it "1 element" $ do
      halve [1] `shouldBe` ([],[1])

    it "2 elements" $ do
      halve [1,2] `shouldBe` ([1],[2])

    it "3 elements" $ do
      halve [1,2,3] `shouldBe` ([1],[2,3])

    it "4 elements" $ do
      halve [1,2,3,4] `shouldBe` ([1,2],[3,4])

Although the rest of the tests pass, the test for 0 elements fails.

No instance for (Show a0) arising from a use of ‘shouldBe’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
  instance Show Double -- Defined in ‘GHC.Float’
  instance Show Float -- Defined in ‘GHC.Float’
  instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
    -- Defined in ‘GHC.Real’
  ...plus 38 others
In a stmt of a 'do' block: halve [] `shouldBe` ([], [])
In the second argument of ‘($)’, namely
  ‘do { halve [] `shouldBe` ([], []) }’
In a stmt of a 'do' block:
  it "0 elements" $ do { halve [] `shouldBe` ([], []) }

When I try it in ghci, it works fine.

*Exercises> halve []
([],[])

Can someone help me?

1

There are 1 answers

1
Jonny Appleseed On

Ah, to answer my own question, I see that I need to make the type more specific. It works if I add halve :: [Int] -> ([Int], [Int]) above my function.

To quote good answers I read in my class's discussion room:

pbl64k

There's certainly no Show instance derivable for lists in general. What about lists of functions? The REPL infers a concrete type that does have a Show instance. But don't expect [a] in general to have one -- unless you make one yourself.

treeowl

pbl64k is sort of right and sort of wrong. There is a Show instance for [a] if there is a Show instance for a. It's automatically derived. The trouble here is that Haskell doesn't know which instance it is. [] may look like a single value, (and in the machine code, it probably is), but at the Haskell level it's a polymorphic constructor. It can take on any list type, so you have to do something to say which list type you mean it to have.