I find Uniplate to be completely the opposite. I always use the
predefine schemes, and they are nearly always exactly what I want.
Whether this is a difference in the traversals provided by the
library, or in the mindset of the user of the library is still up for
debate.

Might help if library author and user are related?-) Or that Uniplate
does generalised selectors/modifiers, while SYB tries to do generalised
everything, which is sometimes too general for its own good? Note that I'm not against Uniplate. I'm just trying to find out whether there are serious reasons why I should be against SYB for the GHC types.

So far, I still think that SYB for GHC types is a good and necessary
first step. If adding Uniplate instances as well gives significant improvements in efficiency or convenience, I won't argue against.

We probably agree on that?

 touches String. Fortunately, all of the traversal schemes
 have very short definitions, and we can define a variant that
 allows us to do something useful with Strings, without traversing them.

Yuk, much better to have something which just works (TM) without these
hacks.

no hacks involved, just a minor variation on everywhere and
everywhereBut:

   everywhereS :: GenericT -> GenericT
   everywhereS f x
       | isString x = f x
       | otherwise  = f (gmapT (everywhereS f) x)

   isString x = typeOf x == typeOf ""

Note that we apply f to Strings (unlike everywhereBut), but don't traverse them (unlike everywhere). Tracing the differences shows the extra work done in a naive traversal:

   g s = trace "*" (mkT (map toUpper) s)
   x = ("there",True)

   *Main> everywhere g x
   *
   ("*
   *
   T*
   *
   H*
   *
   E*
   *
   R*
   *
   E*
   ",*
   True)

   *Main> everywhereBut isString g x
   *
   ("there",*
   True)

   *Main> everywhereS g x
   *
   ("*
   THERE",*
   True)

 Ok, it would be interesting to know how much performance
 remains lost, once a/b are addressed and only c is left (a factor of 2
might not be bad for the added flexibility, and is far lower
 than the factors reported anecdotically, without details)

Yes, but that means someone has to go in and tweak SYB. These things are not trivial.

Actually, the traversal schemes are fairly trivial, and reading the source of Data.Generics.Schemes can be enlightening. Only the underlying gfoldl, etc, and their types, are non-trivial.

and it would be good to know whether there are any other performance killers in typical SYB usage.

I'd guess at no. There are performance overheads (~30%) but no real killers.

I'd be tempted to agree. Just wanted to check whether the
scary anecdotes had anything new to add.

Claus


_______________________________________________
Cvs-ghc mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/cvs-ghc

Reply via email to