Creating instance of Read type class in Haskell for custom data type
Solution 1
The Read typeclass doesn't declare read
directly; instead, it defines readsPrec
, which supports precedence (this is important when read
ing a value of a complex data type involving elements of other types). The definition you get when you use deriving (Read)
looks roughly like
instance (Read a) => Read (Tree a) where
readsPrec d r = readParen (d > app_prec)
(\r -> [(Leaf m,t) |
("Leaf",s) <- lex r,
(m,t) <- readsPrec (app_prec+1) s]) r
++ readParen (d > up_prec)
(\r -> [(u:^:v,w) |
(u,s) <- readsPrec (up_prec+1) r,
(":^:",t) <- lex s,
(v,w) <- readsPrec (up_prec+1) t]) r
where app_prec = 10
up_prec = 5
(this obviously for a Tree
data type, but similar rules apply for other user-defined ADTs). (Also, the above is a slight lie: GHC actually uses a different implementation, but the above is the kind of thing you should do unless you're willing to dig around inside of GHC.)
read
is defined in terms of readsPrec
and readList
(the other method in Read
, which is defaulted for every type except Char
where it's used to read [Char]
as a string instead of as a list of Char
).
If the standard derivation isn't sufficient, for a type like yours that is simply a bucket of Int
s you can ignore the precedence parameter.
BTW, Read
and Show
are rather slow; you may want to consider other ways to do I/O with your data.
Solution 2
That's because the class method that you'd probably want to implement is readsPrec. See here for complete info on Read typeclass: http://zvon.org/other/haskell/Outputprelude/Read_c.html
BTW, you should be able to just use automatic derivation and the compiler will instantiate those Read methods for you e.g.:
data Foo = Foo Int Int
deriving (Read, Show)
Related videos on Youtube
njvb
Updated on July 23, 2020Comments
-
njvb over 3 years
I have a custom data type
Foo = Foo{ a :: Int, b :: Int}
and I'm trying to make Foo a custom instance of read. I already have a functionbar :: String -> Foo
and I tried doing this:instance Read (Foo a b) where read s = bar s
but I'm getting the following error when I load my file into GHCi to test it:
Fraction.hs:11:1: read' is not a (visible) method of class Read'
Could someone tell me what the problem is and how I can actually instantiate this type?
-
njvb over 12 yearsI know I can do that, but I don't really like the way read gets automatically done since it is less intuitive and wanted to make a better version.
-
njvb over 12 yearsdo you have any suggestions for alternatives to read and show?