How to see if type is instance of a class in Haskell?

Posted by Raekye on Stack Overflow See other posts from Stack Overflow or by Raekye
Published on 2013-10-22T03:34:15Z Indexed on 2013/10/22 3:54 UTC
Read the original article Hit count: 88

Filed under:

I'm probably doing this completely wrong (the unhaskell way); I'm just learning so please let me know if there's a better way to approach this.

Context: I'm writing a bunch of tree structures. I want to reuse my prettyprint function for binary trees. Not all trees can use the generic Node/Branch data type though; different trees need different extra data. So to reuse the prettyprint function I thought of creating a class different trees would be instances of:

class GenericBinaryTree a where
    is_leaf :: a -> Bool
    left :: a -> a
    node :: a -> b
    right :: a -> a

This way they only have to implement methods to retrieve the left, right, and current node value, and prettyprint doesn't need to know about the internal structure.

Then I get down to here:

prettyprint_helper :: GenericBinaryTree a => a -> [String]
prettyprint_helper tree
    | is_leaf tree = []
    | otherwise = ("{" ++ (show (node tree)) ++ "}") : (prettyprint_subtree (left tree) (right tree))
        where
            prettyprint_subtree left right =
                ((pad "+- " "|  ") (prettyprint_helper right)) ++ ((pad "`- " "   ") (prettyprint_helper left))
            pad first rest = zipWith (++) (first : repeat rest)

And I get the Ambiguous type variable 'a0' in the constraint: (Show a0) arising from a use of 'show' error for (show (node tree))

Here's an example of the most basic tree data type and instance definition (my other trees have other fields but they're irrelevant to the generic prettyprint function)

data Tree a
    = Branch (Tree a) a (Tree a)
    | Leaf
instance GenericBinaryTree (Tree a) where
    is_leaf Leaf = True
    is_leaf _ = False
    left (Branch left node right) = left
    right (Branch left node right) = right
    node (Branch left node right) = node

I could have defined node :: a -> [String] and deal with the stringification in each instance/type of tree, but this feels neater. In terms of prettyprint, I only need a string representation, but if I add other generic binary tree functions later I may want the actual values.

So how can I write this to work whether the node value is an instance of Show or not? Or what other way should I be approaching this problem? In an object oriented language I could easily check whether a class implements something, or if an object has a method.


I can't use something like

prettyprint :: Show a => a -> String

Because it's not the tree that needs to be showable, it's the value inside the tree (returned by function node) that needs to be showable. I also tried changing node to Show b => a -> b without luck (and a bunch of other type class/preconditions/whatever/I don't even know what I'm doing anymore).

© Stack Overflow or respective owner

Related posts about haskell