[Haskell-cafe] Restricted type classes

Ivan Lazar Miljenovic ivan.miljenovic at gmail.com
Sat Sep 4 04:45:20 EDT 2010


On 4 September 2010 18:27, wren ng thornton <wren at freegeek.org> wrote:
> On 9/4/10 3:50 AM, Ivan Lazar Miljenovic wrote:
>>
>> On 4 September 2010 17:40, wren ng thornton<wren at freegeek.org>  wrote:
>>>
>>> So, in the interest of generality, perhaps you should just pick a letter
>>> or
>>> a short prefix and use that for each of the classes. In my blog posts I
>>> called them 0-monads, 1-monads, and 2-monads; following Ganesh
>>> Sittampalam
>>> and Matthieu Sozeau, they'd be monads, r-monads, and g-monads.
>>
>> I think I'd prefer to put the prefix on the kind * versions (though
>> does a kind * version of something like Monad even make sense?).
>
> Oh sure. I was just meaning that you should do something systematic like
> have XFoo and YFoo, instead of having Foo and Bar. That way people can just
> remember ({X,Y},{Foo,Fob,Fez}) instead of having to remember {(Foo,Bar),
> (Fob,Baz), (Fez,Quux)}.
>
> I'm a fan of keeping the undecorated names for the current versions, and
> using a prefix for the * versions.

Right, so what prefix? ;-)

> Well, liftA and liftM are just generic implementations of fmap using
> pure/(<*>) and return/(>>=). If you can define fmap directly, then you
> should do so. If you can't, you're always free to use the implementations
> that liftA and liftM use. The liftA function is defined explicitly for
> allowing you can say """instance Functor F where fmap = liftA""". There's no
> reason for liftA to belong to Applicative, because it has Functor as a
> superclass and therefore fmap exists. Since fmap can be more efficient than
> liftA, it is better to use fmap when writing code. Note that (<$>) is
> defined as fmap, and liftA2, liftA3, etc are defined in terms of (<$>) i.e.
> fmap.

Gah, you're right.  I didn't think that liftA = fmap.

> For liftM things are a bit hazier because Monad fails to mention Functor as
> an explicit superclass, but it really ought to. Assuming it did, then
> there's no reason for liftM to belong to Monad, because we're assured that
> fmap exists. Though, again, liftM should be defined as a non-class function
> in order to serve as a default implementation of fmap for those who need it.

Hmmm, I was thinking of just having "liftM = fmap", but yeah using the
monadic defaults makes sense to avoid having to define fmap
explicitly.

> This is the same reason why Data.Traversable defines fmapDefault and
> foldMapDefault: not so that they can be used as functions, but so that they
> can be used for giving class instances. Perhaps we should be calling them
> fmapApplictiveDefault, fmapMonadDefault, and fmapTraversableDefault
> instead...
>
> I suppose you could use liftA2 as the basis of Applicative instead of (<*>),
> but that seems a bit perverse to me. The (<*>) operation captures exactly
> what we want to say--- namely the K axiom for modal logics; which is
> equivalent to saying the applicative category has exponentials; which is
> also the name for the whitespace of function application;... . Whereas
> liftA2 seems like a far more round-about way of getting there. There may be
> efficiency reasons for arguing that liftA2 should be included in _addition_
> to (<*>), but I'm not aware of them.

Well,  I _can_ define <*> for Sets (and have done so), but such an
instance doesn't make any sense because functions don't have Ord
instances.  As such, the default liftA2, etc. definitions don't work
with Sets because of this.

-- 
Ivan Lazar Miljenovic
Ivan.Miljenovic at gmail.com
IvanMiljenovic.wordpress.com


More information about the Haskell-Cafe mailing list