Home > Software design >  Simple `Read` instance incorrectly `read`s
Simple `Read` instance incorrectly `read`s

Time:01-20

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.

CodePudding user response:

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.

  • Related