I've been playing around with inductive types (defined natural numbers and arithmetic operations on them) a little bit, and I can't get Haskell read function to work.
Here's my code:
data Natural = Zero | Succ Natural
deriving (Eq, Ord)
instance Enum Natural where
pred Zero = undefined
pred (Succ x) = x
succ x = Succ x
toEnum 0 = Zero
toEnum x = Succ (toEnum (x - 1))
fromEnum Zero = 0
fromEnum (Succ x) = fromEnum x + 1
instance Num Natural where
(+) x Zero = x
(+) x (Succ y) = Succ (x + y)
(-) Zero (Succ x) = undefined
(-) x Zero = x
(-) (Succ x) (Succ y) = x - y
(*) x Zero = Zero
(*) x (Succ y) = x * y + x
abs x = x
signum Zero = Zero
signum (Succ x) = Succ Zero
fromInteger 0 = Zero
fromInteger x = Succ (fromInteger (x - 1))
instance Show Natural where
show x = show $ fromEnum x
-- Not working!
instance Read Natural where
readsPrec x = fromInteger $ (read x) :: Integer
I want this expression to be valid:
naturalNumber = read someStringWithInteger :: Natural
, so I can't just derive Read typeclass.
I've tried using readsPrec
and readPrec
, but I only get mismatched type errors.
How do I implement an instance of Read typeclass?
Your function has the wrong type. Your readsPrec
has type String -> Natural
, whereas you should have used Int -> String -> [(Natural, String)]
. But we can adjust that:
readsPrec p s = [(fromInteger i, s') | (i, s') <- readsPrec p s]
This uses Integer
's readsPrec
function. Since you want to read Integer
s it's just fitting to use it for convenience.
For symmetry reasons, I suggest you to implementshowsPrec
instead of show
in your Show
instance.