{-# OPTIONS -fglasgow-exts #-}
module GMapQAssoc (tests) where
{-
This example demonstrates the inadequacy of an apparently simpler
variation on gmapQ. To this end, let us first recall a few facts.
Firstly, function application (including constructor application) is
left-associative. This is the reason why we had preferred our generic
fold to be left-associative too. (In "The Sketch Of a Polymorphic
Symphony" you can find a right-associative generic fold.) Secondly,
lists are right-associative. Because of these inverse associativities
queries for the synthesis of lists require some extra effort to
reflect the left-to-right of immediate subterms in the queried list.
In the module Data.Generics, we solve the problem by a common
higher-order trick, that is, we do not cons lists during folding but
we pass functions on lists starting from the identity function and
passing [] to the resulting function. The following example
illustrates that we get indeed an undesirable right-to-left order if
we just apply the simple constant datatype constructor CONST instead
of the higher-order trick.
Contributed by Ralf Laemmel, ralf@cwi.nl
-}
import Test.HUnit
import Data.Generics
-- The plain constant type constructor
newtype CONSTxy = CONSTxunCONST (CONSTx) = x-- A variation on the gmapQ combinator using CONST and not QgmapQ' :: Data a => (forall a. Data a =>a -> u) -> a -> [u]
gmapQ'f = unCONST.gfoldlf'z
where
f'ra = CONST (fa:unCONSTr)
z = const (CONST [])
-- A trivial datatype used for this test case
data IntTree = LeafInt | ForkIntTreeIntTreederiving (Typeable, Data)-- Select int if faced with a leaf leaf (Leafi) = [i]
leaf _ = []
-- A test termterm = Fork (Leaf1) (Leaf2)
-- Process test term-- gmapQ gives left-to-right order-- gmapQ' gives right-to-left order--tests = show ( gmapQ ([] `mkQ`leaf) term
, gmapQ' ([] `mkQ`leaf) term
) ~=?outputoutput = show ([[1],[2]],[[2],[1]])