So in one file I have
import Data.String
import MyShow
data Tree a b = Leaf a | Branch b (Tree a b) (Tree a b)
instance (Show a, Show b) => Show (Tree a b) where
show (Branch n t1 t2) = "(" myshow t1 myshow n myshow t2 ")"
show (Leaf l) = myshow l
newtype MyString = MyString String
instance Show MyString where
show (MyString s) = s
and in another file called MyShow.hs I have
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module MyShow where
class MyShow a where
myshow :: a -> String
instance {-# OVERLAPPING #-} MyShow String where
myshow s = s
instance Show a => MyShow a where
myshow = show
When I load the first file in ghci, (Branch " " (Leaf 1) (Leaf 2)
shows (1" "2)
and when I try "(" myshow (Leaf 1) myshow " " myshow (Leaf 2) ")"
, that shows (1 2)
, which is what I want.
What is the reason for this discrepancy and how do I fix it?
CodePudding user response:
Your definition of Show (Tree a b)
only requires a
and b
to have Show
instances, not MyShow
instances. As such (and I don't think I can explain precisely why), the instance of Show a => MyShow a
takes precedence over MyShow String
, because the type checker doesn't know that a
having a MyShow
instance is a possibility.
If you change the constraint to
instance (MyShow a, MyShow b) => Show (Tree a b) where
then show (Branch " " (Leaf 1) (Leaf 2))
will work as expected: myshow " "
will use the MyShow String
instance, not the Show a => MyShow a
instance.