2

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?

Jonny Appleseed
  • 121
  • 1
  • 8
  • 2
    GHCi has `-XExtendedDefaultRules` along with some other rules for showing values that are polymorphic. Try `let x :: Num a => a; x = 1` followed by `x`. It'll print out `1`, without knowing what instance of `Num` to use. The problem here is that when compiled, GHC doesn't know what version of `Show` to use. You could do something like ```halve [] `shouldBe` (([], []) :: ([Int], [Int]))```, ```halve [1] `shouldBe` (([], [1]) :: ([Int], [Int]))```, and so on. Your code is just too polymorphic for GHC to figure out. – bheklilr Nov 16 '14 at 05:02

1 Answers1

5

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.

Community
  • 1
  • 1
Jonny Appleseed
  • 121
  • 1
  • 8
  • Just for fun: It's actually possible to write a list type in haskell that _does_ have a show instance when the list is empty, even if its contents don't - and that is still showable like a normal list if the list isn't empty. That needs a bunch of language extensions to work though, and is quite a bit more difficult to work with because it enforces much stricter static constraints. – Cubic Nov 16 '14 at 07:10