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.



Reply via email to