[Haskell-cafe] generalized newtype deriving allows the definition of otherwise undefinable functions

Wolfgang Jeltsch g9ks157k at acme.softbase.org
Fri Mar 12 04:22:39 EST 2010

Am Donnerstag, 11. März 2010 00:37:18 schrieb wren ng thornton:
> Wolfgang Jeltsch wrote:
> > Hello,
> >
> > some time ago, it was pointed out that generalized newtype deriving could
> > be used to circumvent module borders. Now, I found out that generalized
> > newtype deriving can even be used to define functions that would be
> > impossible to define otherwise. To me, this is surprising since I thought
> > that generalized newtype deriving was only intended to save the
> > programmer from writing boilerplate code, not to extend expressiveness.
> Let's dig down and figure out the problem. When you annotate the type
> "Wrapped a" with "deriving (Iso a)" what are you saying? You're saying
> that the compiler should derive an instance (Iso a (Wrapped a)). Well,
> that instance gives you the method instance conv :: forall f. f a -> f
> (Wrapped a). The funny thing is that the only implementation for
> ---something like--- that type would be fmap Wrap.

If the parameter of f is contravariant then we would need a “contraMap”, not 
an fmap. Example:

> newtype CoFun a b = CoFun (b -> a)
> class ContraFunctor f where
>     contraMap :: (a -> b) -> f b -> f a
> instance ContraFunctor (CoFun a) where
>     contraMap f (CoFun g) = CoFun (g . f)
> coFun :: CoFun Int Char
> coFun = CoFun ord
> directlyConverted :: CoFun Int (Wrapped Char)
> directlyConverted = conv coFun
> manuallyConverted :: CoFun Int (Wrapped Char)
> manuallyConverted = contraMap unwrap coFun

Here, unwrap is the inverse of Wrap.

Let us look at the Set example from John Meacham. Set is a (covariant) 
functor, not a contravariant functor. However, it isn’t a functor from and to 
the category of Haskell types and functions but the category of types of class 
Ord and Ord homomorphisms (functions that respect ordering). The problem in 
John Meacham’s Set example is that Down doesn’t preserve ordering. If conv is 
used with a newtype wrapper constructor that does preserve ordering, this is 
the same as applying Set.map or Set.mapMonotonic.

Best wishes,

More information about the Haskell-Cafe mailing list