Search code examples
haskell

Simple `Read` instance incorrectly `read`s


Why does this Read instance parse inconsistently?

import qualified Data.List as List

data Foo = Foo

instance Show Foo where
  show _ = "Foo"

instance Read Foo where
  readsPrec _ s = case List.stripPrefix "Foo" s of
    Just rest -> [(Foo, rest)]
    Nothing -> []

This is expected:

Test> reads "" :: [(Foo, String)]
[]

This is unexpected:

Test> read "" :: Foo
Foo

I would expect it to throw.


Solution

  • The problem isn't in read, but in show. Your show implementation doesn't force the input value of type Foo, because it returns "Foo" unconditionally, without even matching a constructor. If you use the derived Show instance, or write its equivalent by hand:

    instance Show Foo where
      show Foo = "Foo"
    

    then you will get the expected error when you try to parse a malformed string, because evaluating show will actually require parsing the input string.