Graeme Moss asks about "map" defined over this type:
> newtype MyList a = MyList [a]
using variously case, an auxiliary function, a selector function, and
pattern guards.
> Should any of these rather cumbersome ways of defining the standard
> map over (MyList a) cause any more code than the standard definition
> of map over lists?
Not that I know of, given a reasonable attempt at inlining and
simplifying the extra functions in 2) and 3); there's the possibility of
losing map-specific optimisations, but that wouldn't be true of some
arbitrary function over lists, which I assume is the thrust of your
question. For the grubby details, though, you might have to crosspost
to {ghc,hbc}-implementors-confessions-list.
> Is there a more elegant way of defining map over (MyList a)?
I hestitate to say "more elegant", but I'd probably have used:
> myMap5 :: (a -> b) -> MyList a -> MyList b
> myMap5 f (MyList []) = MyList []
> myMap5 f (MyList (x:xs)) = MyList (f x:ys)
> where MyList ys = myMap5 f (MyList xs)
or perhaps a "let" rather than a where. Lambda-fiends might even
prefer a (\MyList ys -> MyList (f x:ys)) (myMap5 f (MyList xs))
-- though I can't really imagine why.
> I find it easy to tag a list to convert it to the type (MyList a), but
> un-tagging (MyList a) to convert it back to [a] I find rather
> cumbersome.
This is true for Haskell algebraic types in general, simply because
you get the constructor for free, but have to define all your own
selectors. Named fields are a partial solution to this; another
would be some sort of meta-deriving facility, to cause test and
select functions to be generated automatically, but that's probably
more inelegance than is justified by the possible convenience.
Slainte,
Alex.