TheZouave
TheZouave

Reputation: 73

Haskell Show bug?

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?

Upvotes: 0

Views: 109

Answers (1)

chepner
chepner

Reputation: 531165

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.

Upvotes: 5

Related Questions