# contravariant functors!

8 replies
extempore
Joined: 2008-12-17,

I added map to Ordering, but because of its natural contrariness the
argument "goes the other way" compared to the usual map.

Ordering[T] { ...
def map[U](f: U => T): Ordering[U] = new Ordering[U] {
def compare(x: U, y: U) = outer.compare(f(x), f(y))
}

So a question: should this use a different name than map? Another
context in which this has arisen for me is Numeric, where I have a
branch somewhere which creates derivative Numerics and allows for fun
stuff like automatically reversible functions.

I also added jorge's sortBy to SeqLike, marked @experimental pending
approval. It is indeed pretty nice to be able to do:

val words = "The quick brown fox jumped over the lazy dog".split(' ')
res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped)

Jorge Ortiz
Joined: 2008-12-16,
Re: contravariant functors!
Haskell calls it 'on'. I called it 'by' (added it only as a static method on object Ordering, but considered it as a method on trait Ordering as well). I don't think 'map' is an appropriate name.

--j

On Thu, Oct 22, 2009 at 9:36 AM, Paul Phillips <paulp [at] improving [dot] org> wrote:
I added map to Ordering, but because of its natural contrariness the
argument "goes the other way" compared to the usual map.

Ordering[T] { ...
def map[U](f: U => T): Ordering[U] = new Ordering[U] {
def compare(x: U, y: U) = outer.compare(f(x), f(y))
}

So a question: should this use a different name than map? Another
context in which this has arisen for me is Numeric, where I have a
branch somewhere which creates derivative Numerics and allows for fun
stuff like automatically reversible functions.

I also added jorge's sortBy to SeqLike, marked @experimental pending
approval.  It is indeed pretty nice to be able to do:

val words = "The quick brown fox jumped over the lazy dog".split(' ')
res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped)

--
Paul Phillips      | These are the climbs that apply men's soles.
Imperfectionist    |
Empiricist         |
slap pi uphill!    |----------* http://www.improving.org/paulp/ *----------

extempore
Joined: 2008-12-17,
Re: contravariant functors!

On Thu, Oct 22, 2009 at 09:44:29AM -0700, Jorge Ortiz wrote:
> Haskell calls it 'on'. I called it 'by' (added it only as a static
> method on object Ordering, but considered it as a method on trait
> Ordering as well). I don't think 'map' is an appropriate name.

Yeah, I agree map is no good, if only because the signature is wrong.
But it feels like it ought to have a mappy name, like say "comap", and
not some completely different term.

extempore
Joined: 2008-12-17,
Re: contravariant functors!

On Thu, Oct 22, 2009 at 09:44:29AM -0700, Jorge Ortiz wrote:
> Haskell calls it 'on'. I called it 'by' (added it only as a static
> method on object Ordering, but considered it as a method on trait
> Ordering as well). I don't think 'map' is an appropriate name.

As near as I can tell, Haskell calls it "cofmap" (since "fmap" is the
functor map.) I am finding "on" a difficult thing to google, can you
point me at what you mean? Here is cofmap:

That said I am fine with continuing to resist the invasion of category
theory in scalaland, but I'm having trouble coming up with an obvious
winner for alternate name. Sure 'on' and 'by' are plausible but they
also seem arbitrary, not to mention unrevealing.

dcsobral
Joined: 2009-04-23,
Re: contravariant functors!
I'm borderline on understanding it, but I can't make the leap for some reason. Could you post one usage example?

On Thu, Oct 22, 2009 at 2:36 PM, Paul Phillips <paulp [at] improving [dot] org> wrote:
I added map to Ordering, but because of its natural contrariness the
argument "goes the other way" compared to the usual map.

Ordering[T] { ...
def map[U](f: U => T): Ordering[U] = new Ordering[U] {
def compare(x: U, y: U) = outer.compare(f(x), f(y))
}

So a question: should this use a different name than map? Another
context in which this has arisen for me is Numeric, where I have a
branch somewhere which creates derivative Numerics and allows for fun
stuff like automatically reversible functions.

I also added jorge's sortBy to SeqLike, marked @experimental pending
approval.  It is indeed pretty nice to be able to do:

val words = "The quick brown fox jumped over the lazy dog".split(' ')
res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped)

--
Paul Phillips      | These are the climbs that apply men's soles.
Imperfectionist    |
Empiricist         |
slap pi uphill!    |----------* http://www.improving.org/paulp/ *----------

--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
Jorge Ortiz
Joined: 2008-12-16,
Re: contravariant functors!
Let me Hoogle that for you... ;)

--j

On Thu, Oct 22, 2009 at 12:29 PM, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Thu, Oct 22, 2009 at 09:44:29AM -0700, Jorge Ortiz wrote:
> Haskell calls it 'on'. I called it 'by' (added it only as a static
> method on object Ordering, but considered it as a method on trait
> Ordering as well). I don't think 'map' is an appropriate name.

As near as I can tell, Haskell calls it "cofmap" (since "fmap" is the
functor map.) I am finding "on" a difficult thing to google, can you
point me at what you mean? Here is cofmap:

That said I am fine with continuing to resist the invasion of category
theory in scalaland, but I'm having trouble coming up with an obvious
winner for alternate name.  Sure 'on' and 'by' are plausible but they
also seem arbitrary, not to mention unrevealing.

--
Paul Phillips      | It is hard to believe that a man is
Caged Spirit       | telling the truth when you know that you
Empiricist         | would lie if you were in his place.
pp: i haul pills   |     -- H. L. Mencken

Jorge Ortiz
Joined: 2008-12-16,
Re: contravariant functors!
Daniel:

If the new method is called "comap", and Orderint[T] returns an instance of an Ordering for T, then:

case class Person(name: String, age: Int)

Ordering[Int].comap((p: Person) => p.age) // returns Ordering[Person], by age
Ordering[String].comap((p: Person) => p.name) // returns Ordering[Person], by name

--j

On Thu, Oct 22, 2009 at 12:52 PM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
I'm borderline on understanding it, but I can't make the leap for some reason. Could you post one usage example?

On Thu, Oct 22, 2009 at 2:36 PM, Paul Phillips <paulp [at] improving [dot] org> wrote:
I added map to Ordering, but because of its natural contrariness the
argument "goes the other way" compared to the usual map.

Ordering[T] { ...
def map[U](f: U => T): Ordering[U] = new Ordering[U] {
def compare(x: U, y: U) = outer.compare(f(x), f(y))
}

So a question: should this use a different name than map? Another
context in which this has arisen for me is Numeric, where I have a
branch somewhere which creates derivative Numerics and allows for fun
stuff like automatically reversible functions.

I also added jorge's sortBy to SeqLike, marked @experimental pending
approval.  It is indeed pretty nice to be able to do:

val words = "The quick brown fox jumped over the lazy dog".split(' ')
res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped)

--
Paul Phillips      | These are the climbs that apply men's soles.
Imperfectionist    |
Empiricist         |
slap pi uphill!    |----------* http://www.improving.org/paulp/ *----------

--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.

Jorge Ortiz
Joined: 2008-12-16,
Re: contravariant functors!
Looking at that code I just wrote, I'm unhappy, especially because of the implicit nature of getting Orderings.

As a static method "by" on Ordering, you don't need to explicitly find the Ordering[Int] or the Ordering[String].

Ordering.by((p: Person) => p.age) // Ordering[Person], by age (Ordering[Int] found implicitly)
Ordering.by((p: Person) => p.name) // Ordering[Person], by name (Ordering[String] found implicitly)

And if the expected return type is already an Ordering[Person], then you can be even more concise:

Ordering.by(_.age)
Ordering.by(_.name)

--j

On Thu, Oct 22, 2009 at 3:55 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
Daniel:

If the new method is called "comap", and Orderint[T] returns an instance of an Ordering for T, then:

case class Person(name: String, age: Int)

Ordering[Int].comap((p: Person) => p.age) // returns Ordering[Person], by age
Ordering[String].comap((p: Person) => p.name) // returns Ordering[Person], by name

--j

On Thu, Oct 22, 2009 at 12:52 PM, Daniel Sobral <dcsobral [at] gmail [dot] com> wrote:
I'm borderline on understanding it, but I can't make the leap for some reason. Could you post one usage example?

On Thu, Oct 22, 2009 at 2:36 PM, Paul Phillips <paulp [at] improving [dot] org> wrote:
I added map to Ordering, but because of its natural contrariness the
argument "goes the other way" compared to the usual map.

Ordering[T] { ...
def map[U](f: U => T): Ordering[U] = new Ordering[U] {
def compare(x: U, y: U) = outer.compare(f(x), f(y))
}

So a question: should this use a different name than map? Another
context in which this has arisen for me is Numeric, where I have a
branch somewhere which creates derivative Numerics and allows for fun
stuff like automatically reversible functions.

I also added jorge's sortBy to SeqLike, marked @experimental pending
approval.  It is indeed pretty nice to be able to do:

val words = "The quick brown fox jumped over the lazy dog".split(' ')
res0: Array[String] = Array(The, dog, fox, the, lazy, over, brown, quick, jumped)

--
Paul Phillips      | These are the climbs that apply men's soles.
Imperfectionist    |
Empiricist         |
slap pi uphill!    |----------* http://www.improving.org/paulp/ *----------

--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.

Nick Partridge
Joined: 2009-10-23,
Re: contravariant functors!
Scalaz calls it 'comap'. And of course, it provides it in a more general and useful way.
- Nick*
(* Filling in for Tony while he's on his holiday.)

On Fri, Oct 23, 2009 at 5:29 AM, Paul Phillips <paulp [at] improving [dot] org> wrote:
On Thu, Oct 22, 2009 at 09:44:29AM -0700, Jorge Ortiz wrote:
> Haskell calls it 'on'. I called it 'by' (added it only as a static
> method on object Ordering, but considered it as a method on trait
> Ordering as well). I don't think 'map' is an appropriate name.

As near as I can tell, Haskell calls it "cofmap" (since "fmap" is the
functor map.) I am finding "on" a difficult thing to google, can you
point me at what you mean? Here is cofmap: