
On Sun, May 8, 2011 at 7:14 AM, Nicholas Tung
Dear all, I'd like to write a function "maybeShow :: a -> Maybe String", which runs "show" if its argument is of class Show. The context and motivation for this are as follows. I have a GADT type which encapsulates abstract-value computation (or constants or error codes), a snippet of which is below. data AV t where AVLeft :: AV a -> AV (Either a b) This is used to implement an arrow transformer, and due to Arrows mapping all Haskell functions, I cannot put some kind of qualification on the constructor, like "AVLeft :: Show a => ...". Of course any replies are welcome, but I do need something implemented and stable. If there are GHC-compatible hacks, even an "unsafeShow :: a -> String", that'd be great. I'd also prefer not to branch on all types which could possibly be maybeShow's argument.
To the best of my knowledge, this is impossible. Haskell/GHC lets you require that certain type-level (predicates/assertions/constraints be true? evidence/proof be supplied? I'm not sure what the correct terminology is), but it doesn't let you branch over *whether* it is so. A natural solution would be OverlappingInstances, but that doesn't help in this case: instances are matched only by the instance head, and the context is checked only afterwards. So if you have class MaybeShow a where maybeShow :: a -> Maybe String instance MaybeShow a where maybeShow = const Nothing instance Show a => MaybeShow a where maybeShow = Just . show you have two instances which both match for any 'a', resulting in overlap any time you try to use it, and rendering this 'solution' unworkable. There's a section on advanced overlap in the wiki[1], but it's Really Ugly and doesn't (to my mind) actually solve the problem (you still have to branch on every potential type). You could do: class MaybeShow a where maybeShow :: a -> Maybe String instance MaybeShow a where maybeShow = const Nothing newtype Showable a = Showable { getShowable :: a } instance Show a => MaybeShow (Showable a) where maybeShow = Just . show . getShowable which lets you write further MaybeShow instances for specific types to 'forward' the Show instance (which isn't any worse than the AdvancedOverlap solution, if you have to handle every type explicitly anyways), and you can also write maybeShow (Showable x) at the use site if you know that x has a Show instance. But at that point you might as well perform some 'optimization' and just use show directly, so this doesn't really get you anywhere. [1] http://www.haskell.org/haskellwiki/GHC/AdvancedOverlap
(Concretely, if I have "newtype AVFunctor a b c = AVF (a (AV b) (AV c))", then the Arrow class declaration forces all types, c.f. variable b, to be potential variables of type AV), class (Category a) => Arrow a where arr :: (b -> c) -> a b c
Thanks very much, Nicholas — https://ntung.com — CS major @ UC Berkeley
p.s. I posted this question on StackOverflow if you care to get brownie points there, http://goo.gl/PrmYW p.s. 2 -- if there is a general "dump var" function in ghci, which does more than ":info", I'd love to know :) _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Work is punishment for failing to procrastinate effectively.