RE: [Haskell-cafe] Proposal: deriving ShallowEq?

-----Original Message----- From: haskell-cafe-bounces@haskell.org [mailto:haskell-cafe- bounces@haskell.org] On Behalf Of Bulat Ziganshin Sent: Tuesday, July 19, 2005 1:18 AM To: Ben Lippmeier Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Proposal: deriving ShallowEq?
Hello Ben,
Tuesday, July 19, 2005, 11:01:32 AM, you wrote: BL> I often find it useful to determine whether two objects are using
As Bulat points out, the GHC primitive dataToTag# indeed nicely solves the problem. Ben, just for completeness' sake; with SYB, you get such reflective information too (and others): shallowEq :: Data a => a -> a -> Bool shallowEq x y = toConstr x == toConstr y (dataToTag# returns Int, while toConstr comprises other things like the constructor name.) Regards, Ralf the
BL> same constructor, without worrying about the constructors' arguments.
BL> There is way to hack together a partial implementation of the ShallowEq BL> class within GHC, but it leaves much to be desired:
BL> > instance Show a => ShallowEq a where BL> > (=@=) a b BL> > = (head $ words $ show a) == (head $ words $ show b)
reading GHC sources is always very interesting :)
that is from GHC/Base.hs :
%********************************************************* %* * \subsection{@getTag@} %* * %*********************************************************
Returns the 'tag' of a constructor application; this function is used by the deriving code for Eq, Ord and Enum.
The primitive dataToTag# requires an evaluated constructor application as its argument, so we provide getTag as a wrapper that performs the evaluation before calling dataToTag#. We could have dataToTag# evaluate its argument, but we prefer to do it this way because (a) dataToTag# can be an inline primop if it doesn't need to do any evaluation, and (b) we want to expose the evaluation to the simplifier, because it might be possible to eliminate the evaluation in the case when the argument is already known to be evaluated.
\begin{code} {-# INLINE getTag #-} getTag :: a -> Int# getTag x = x `seq` dataToTag# x \end{code}
-- Best regards, Bulat mailto:bulatz@HotPOP.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Ralf Lammel wrote:
As Bulat points out, the GHC primitive dataToTag# indeed nicely solves the problem. Ben, just for completeness' sake; with SYB, you get such reflective information too (and others):
shallowEq :: Data a => a -> a -> Bool shallowEq x y = toConstr x == toConstr y
(dataToTag# returns Int, while toConstr comprises other things like the constructor name.)
Ralf, Yes, I ended up using the "propper" SYB approach instead, though I have noticed that the reflection data types Constr and DataRep make no mention of type variables or functions. For example, this works fine:
getTag (Just 5) ==# getTag (Just{}) getTag (Just (\x -> x)) ==# getTag (Just{})
But this does not
toConstr (Just 5) == toConstr (Just{}) Ambiguous type variables.
toConstr (Just (\x -> x)) == toConstr (Just{}) No instance for Data (t -> t)
I appreciate the reasons why this is so, though I think it's interesting to see the practical consequences. A toConstr version of shallowEq works ok so long as you provide a type signature to constrain both arguments to be the same type, and one of them is always fully constructed - which is fine for me at the moment. Ben.
participants (2)
-
Ben Lippmeier
-
Ralf Lammel