[Haskell-beginners] How to write Read instance

Baa aquagnu at gmail.com
Thu Nov 2 14:51:06 UTC 2017


Hello, David!

`Show` instance is simple:

  instance Show Hex where
    show = T.unpack . ghValue

so

  > show (Hex "1234ab")
  1234ab
  > read "1234ab"::Hex
  1234ab
  > read "Just 1234ab"::Maybe Hex -- fails like wrapped in the record!!

Yes, I'm ignoring precedence usually too. And I return rest of the
string. Playing with `UTCTime`'s readsPrec shows me that behaviour
looks the same: UTCTime's reader returns the same rest. So, may be
trick is in the:

1. Precedence ?!
2. readListPrec = readListPrecDefault
   readList     = readListDefault   ?

   But I get error: readListPrec is not visible method of class Read...
3. readPrec ? I implemented readsPrec which is old-style, but am I
   right that old-style and new-style are absolutely the same from
   reading point of view and old-style can replace new-style and vice
   versa?

PS. I don't import any special modules.


> The most common way is to just auto derive Read.  I'm not sure that
> that ever really fails.  Are you sure the problem isn't with the Show
> instance of the type?  People commonly write invalid Show instances
> to make them look pretty and they shouldn't.  read and show are
> supposed to be inverses of each other because when they aren't,
> problems like this occur.
> 
> The simple way to do a Read instance is to implement the reads
> function for it.  The confusion comes from its type.  readsPrec ::
> Int -> ReadS a. ReadS is defined as String -> [(a, String)], where a
> is the parsed result and String is the rest of the string that is
> being parsed, , which may look confusing, and the Int is precedence,
> which can usually be ignored.  It could have been Int -> String ->
> Maybe (a, String), but Read predates Maybe.  So instead it returns a
> list and if it fails to parse, it returns [] instead of Nothing.  So.
> 
> data MyFoo = MyFoo
> 
> instance Read MyFoo where
>   -- readsPrec :: Int -> String -> [(MyFoo, String)]
>   readsPrec _ = readFoo
> 
> readFoo :: String -> [(MyFoo, String)]
> readFoo str = case splitAt 5 str of
>   ("MyFoo", rest) -> [(MyFoo, rest)]
>   otherwise -> []
> 
> If you need something more complex, there are functions to do it in
> base that perform lexing and parsing.  I have never used them but you
> can go ahead and read some of the instances such as Ordering at
> https://hackage.haskell.org/package/base-4.10.0.0/docs/src/GHC.Read.html#line-398
> to try and learn how it might work for you.
> 
> But honestly I think you should look at fixing your Show instance
> first, if possible.
> 
> 
> On Thu, Nov 2, 2017 at 9:41 AM, Baa <aquagnu at gmail.com> wrote:
> 
> > Hello all!
> >
> > I found some errors in the reading of previously shown big and
> > complex record. Reason is: some of fields are reading wrongly. So,
> > is there any useful documents how to write `Read` instance correctly
> > (because I can't find good tutorial in the Web and often hit errors
> > with `Read` instance)? May be tutorial/examples/any good info...
> >
> >
> > ===
> > Best regards, Paul
> > _______________________________________________
> > Beginners mailing list
> > Beginners at haskell.org
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >  



More information about the Beginners mailing list