4

I have created a type similar to Maybe

data Defined a = Is a | Undefined

I made the Show instnance

instance Show a => Show (Defined a) where
    show (Is a) = show a
    show Undefined = "?"

So, I try to implement the instance Read

instance Read a => Read (Defined a) where
    readsPrec _ s = case (take 1 s) of
                    "?" -> [(Undefined,tail s)]
                    otherwise -> map (\(a,b) -> (Is a,b)) $ readsPrec 0 s

That's work, but I can't understand why. Why there is no infinite loop here:

otherwise -> map (\(a,b) -> (Is a,b)) $ readsPrec 0 s

readsPrec 0 s try to read the same string such as in input, isn't it? So it have to go to otherwise block yet and form an infinite loop. But the code is really works.

7
  • 1
    Note that such Show and Read instances are shunned in Haskell: show should produce valid Haskell code, so "?" won't do as a result. If what you're trying to do is just pretty printing, e.g. for ghci, then you should stay with the Maybe container and just use a suitable pretty-printing function. Commented Feb 11, 2015 at 14:52
  • It's maybe not a good idea for me to use the standard Maybe container because I made the Eq instance of Defined type with differing behaviour Commented Feb 11, 2015 at 15:00
  • An Eq instance with differing behaviour? I wager that's an even worse idea (but if you properly hide the Undefined constructor, it might be ok). At any rate, you shouldn't let the show (Is a) print out only the a value, without ever mentioning it was wrapped in a Defined. Commented Feb 11, 2015 at 15:05
  • (Nothing == Nothing) is True in the implementation of Eq for Maybe that's not I want for Defined type, so I have to create my own type or overload Eq for Maybe that's even worse. Commented Feb 11, 2015 at 15:19
  • 5
    Well, but you should not want Undefined == Undefined to be false! At least not unless Undefined is really some kind of exceptional value that wouldn't ever appear in applications. (Yes, I know that analogously, for floating-point numbers IEEE754 specifies NaN == NaN to be false, but that's truely a horrible hack that has caused lots of problems of its own.) Commented Feb 11, 2015 at 15:25

1 Answer 1

6

readsPrec 0 s try to read the same string such as in input, isn't it?

Yes it is, but it's not the same readsPrec! Let me add a few type annotations:

{-# LANGUAGE ScopedTypeVariables #-}

instance Read a => Read (Defined a) where
  readsPrec _ = readsDefined

readsDefined :: forall a . Read a => String -> ReadS (Defined a)
readsDefined s = case (take 1 s) of
                    "?" -> [(Undefined,tail s)]
                    otherwise -> map (\(a,b) -> (Is a,b)) $ readsContent s
 where readsContent :: String -> ReadS a
       readsContent = readsPrec 0

Note that I can not replace readsContent with readsDefined here, they're two different functions with incompatible type signature. That's the same situation as in your code, only, there readsDefined and readsContent are both (different) instantiations of the readsPrec method, i.e. they share the same name but still have different implementations.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.