[Haskell-beginners] How to write Read instance

Baa aquagnu at gmail.com
Thu Nov 2 15:13:43 UTC 2017


Does it work with wrapping in records, in "Just" ?
Would you show this example, please?

I try this:

  import qualified Data.Text           as T
  import           GHC.Read
  import qualified Data.Char           as C

  newtype GitHash = GitHash { ghValue :: T.Text } deriving (Eq, Ord, Generic)

  instance Show GitHash where
    show = T.unpack . ghValue

  instance Read GitHash where
    readsPrec p = readParen (p > 10) reader where
      reader :: ReadS GitHash
      reader s =
         case span C.isHexDigit s of
           ([], _)      -> []
           (hex, nohex) -> [(GitHash $ T.pack hex, nohex)]
    readListPrec = readListPrecDefault
    readList     = readListDefault

and this parses:

  > read "1234ab"::GitHash

but not this:

  > read "Just 1234"::Maybe GitHash
  *** Exception: Prelude.read: no parse



> My own toy example works.  I don't know how yours differs.
> 
> On Thu, Nov 2, 2017 at 10:51 AM, Baa <aquagnu at gmail.com> wrote:
> 
> > 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
> > > >  
> >
> > _______________________________________________
> > Beginners mailing list
> > Beginners at haskell.org
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
> >  



More information about the Beginners mailing list