[Haskell-cafe] generalized newtype deriving allows the definition
of otherwise undefinable functions
wren ng thornton
wren at freegeek.org
Fri Mar 12 21:59:33 EST 2010
Wolfgang Jeltsch wrote:
> 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:
Right, but it's the same basic idea, just violating the (nonexistent?)
ContraFunctor class instead of the Functor class. The underlying problem
---which is what I was trying to identify--- is that generalized newtype
deriving is assuming that every tycon of kind *->* is a functor (i.e.,
co-/contravariant endofunctor on all of Hask), and it's that assumption
which causes breakage.
My conservative solution to disallow deriving methods where the newtype
occurs beneath an "unknown" tycon would, I think, still work. The only
difference is that in addition to considering all instances of
Functor[1] as "well known" (as well as a few special cases: e.g., the
first argument to (->) or (,)) we could consider all instances of
ContraFunctor to be "well known" as well. That is, if there's an
official version of that class.
My solution is conservative in that it doesn't offer any support for
GADTs or type families, which are the particular concern in the bug
tracker ticket. The problem for them is the same one, only it's even
more pertinent since some things given the kind *->* should really have
a different kind like |*|->* since their argument is an index instead of
a type--- which means they're _really_ not functors on Hask.
> 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
Right, which is why the assumption that kind *->* implies functorality
is broken. Again, in some sense even the kind is wrong; it's something
more like Ord->*, but that only underscores the point.
[1] And Monad since Monad doesn't state the Functor requirement.
--
Live well,
~wren
More information about the Haskell-Cafe
mailing list