[Haskell-cafe] Types and Trees

Matt Morrow mjm2002 at gmail.com
Wed Sep 3 08:06:48 EDT 2008


I really learned a lot from writing the below code,
and thought I'd share it with the group. I'm slightly
at a loss for words, having just spent the last two
hours on this when I most certainly should have
been doing other work, but these are two hours
I won't regret. I'm very interested in hearing
others' thoughts on "this", where "this" is
"whatever comes to mind".

Regards,
Matt

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

module TT where

import Data.Tree
import Data.Typeable
 (Typeable(..),TypeRep(..),TyCon(..)
 ,typeRepTyCon,typeRepArgs,tyConString)
import Language.Haskell.TH(Type(..),mkName)

--------------------------------------------------------

class ToType a where
 toType :: a -> Type

class ToTree a b where
 toTree :: a -> Tree b

{-
       Typeable a
           |
 typeOf | (0)
           |
           v             toType
         TypeRep  - - - - - - - - >  Type
           |                 (4)             |
 toTree | (1)                       (2) | toTree
           |                                  |
           v                 (3)            v
       Tree TyCon  --------------->  Tree Type
                             toTree

-}

-- (0)
typeableToTypeRep :: (Typeable a) => a -> TypeRep
typeableToTypeRep = typeOf

-- (1)
instance ToTree TypeRep TyCon where
 toTree ty = Node (typeRepTyCon ty)
   (fmap toTree . typeRepArgs $ ty)

-- (2)
instance ToTree Type Type where
 toTree (AppT t1 t2) =
   let (Node x xs) = toTree t1
   in Node x (xs ++ [toTree t2])
 toTree t = Node t []

-- (3.a)
instance ToType TyCon where
 toType tyC = let tyS = tyConString tyC
   in case tyS of
       "->"            -> ArrowT
       "[]"            -> ListT
       "()"            -> TupleT 0
       ('(':',':rest)  -> let n = length
                               (takeWhile (==',') rest)
                          in TupleT (n+2)
       _               -> ConT . mkName $ tyS

-- (3.b)
instance ToType (Tree TyCon) where
 toType (Node x xs) =
   foldl AppT (toType x)
           (fmap toType xs)

-- (3)
instance ToTree (Tree TyCon) Type where
 toTree = toTree . toType

-- (4)
instance ToType TypeRep where
 toType = toType . (toTree::TypeRep->Tree TyCon)

-- (0)  typeOf
-- (1)  toTree
-- (2)  toTree
-- (3)  toTree
-- (4)  toType

-- (0) -> (1)
tyConTree :: (Typeable a) => a -> Tree TyCon
tyConTree = toTree . typeOf

-- (0) -> (1) -> (3)
typeTree_a :: (Typeable a) => a -> Tree Type
typeTree_a = (toTree::Tree TyCon->Tree Type)
             . (toTree::TypeRep->Tree TyCon)
               . typeOf

-- (0) -> (4) -> (2)
typeTree_b :: (Typeable a) => a -> Tree Type
typeTree_b = (toTree::Type->Tree Type)
             . (toType::TypeRep->Type)
               . typeOf


diagram_commutes :: (Typeable a) => a -> Bool
diagram_commutes a = typeTree_a a == typeTree_b a

-- ghci> diagram_commutes x0
-- True
x0 :: (Num a) => ((a,(a,((a,a),a))),(a,(a,a)))
x0 = ((0,(0,((0,0),0))),(0,(0,0)))

--------------------------------------------------------

printTree :: (Show a) => Tree a -> IO ()
printTree = putStr . drawTree . fmap show

printForest :: (Show a) => Forest a -> IO ()
printForest = putStr . drawForest . (fmap . fmap) show

--------------------------------------------------------
{-

ghci> printTree $ tyConTree  x0
(,)
|
+- (,)
|  |
|  +- Integer
|  |
|  `- (,)
|     |
|     +- Integer
|     |
|     `- (,)
|        |
|        +- (,)
|        |  |
|        |  +- Integer
|        |  |
|        |  `- Integer
|        |
|        `- Integer
|
`- (,)
  |
  +- Integer
  |
  `- (,)
     |
     +- Integer
     |
     `- Integer


ghci> printTree $ typeTree_a x0
TupleT 2
|
+- TupleT 2
|  |
|  +- ConT Integer
|  |
|  `- TupleT 2
|     |
|     +- ConT Integer
|     |
|     `- TupleT 2
|        |
|        +- TupleT 2
|        |  |
|        |  +- ConT Integer
|        |  |
|        |  `- ConT Integer
|        |
|        `- ConT Integer
|
`- TupleT 2
  |
  +- ConT Integer
  |
  `- TupleT 2
     |
     +- ConT Integer
     |
     `- ConT Integer


ghci> printTree $ typeTree_b x0
TupleT 2
|
+- TupleT 2
|  |
|  +- ConT Integer
|  |
|  `- TupleT 2
|     |
|     +- ConT Integer
|     |
|     `- TupleT 2
|        |
|        +- TupleT 2
|        |  |
|        |  +- ConT Integer
|        |  |
|        |  `- ConT Integer
|        |
|        `- ConT Integer
|
`- TupleT 2
  |
  +- ConT Integer
  |
  `- TupleT 2
     |
     +- ConT Integer
     |
     `- ConT Integer

-}
--------------------------------------------------------


More information about the Haskell-Cafe mailing list