
Also sent to comp.lang.haskell, & to convince Gmane I'm not top-posting.
It is with some shame that I announce ‘true-name’, a package to assist one in violating those pesky module abstraction boundaries via the magick of Template Haskell. http://hackage.haskell.org/package/true-name Take ‘Control.Concurrent.Chan’ for example; you can get your grubby mitts on the ‘Chan’ data constructor, despite it not being exported. Here we pattern match on it, and bind ‘chanR’ and ‘chanW’ to the ‘MVar’s containing the read and write ends of the channel respectively:
chan@[truename| ''Chan Chan | chanR chanW |] <- newChan writeChan chan (42 :: Int)
Now, the type of ’chanR’ references the unexported ‘Stream’ and ‘ChItem’ types. We need the ‘ChItem’ data constructor―which is hidden under a few indirections—but that's not a problem:
streamR <- readMVar chanR [truename| ''Chan Chan Stream ChItem ChItem | x _ |] <- readMVar streamR putStrLn $ "chan contains: " ++ show x
This gives us a rather dodgy ‘peekChan’. This sort of thing is usually a Bad Idea™, but may sometimes be more palatable than the alternatives. Full example: https://github.com/liyang/true-name/blob/master/sanity.hs Taking another example, suppose we want the ‘Array’ type constructor hidden deep in the bowels of the ‘HashMap’ implementation: ghci> :set -XQuasiQuotes ghci> import Data.HashMap.Strict ghci> :kind [truename| ''HashMap Full Array |] [truename| ''HashMap Full Array |] :: * -> * The ‘Array’ data constructor is one more reification away: ghci> :type [truename| ''HashMap Full Array Array |] [truename| ''HashMap Full Array Array |] :: ghc-prim-0.4.0.0:GHC.Prim.Array# a -> unordered-containers-0.2.5.1:Data.HashMap.Array.Array a Please don't flame me. /Liyang