GithubHelp home page GithubHelp logo

Comments (14)

krishnanraman avatar krishnanraman commented on July 17, 2024

Personally, I would prefer Abelian.
Commutes is very colloquial within the math circles & that's fine too.
So have a marker trait Abelian. ( no val's etc. just a trait )
All cyclic groups will necessarily extend Abelian.
By default, groups aren't going to be abelian, so they won't extend it. No need for this isCommutative, isNotCommutative, CommutativeStatus etc.

from algebird.

sritchie avatar sritchie commented on July 17, 2024

I think @krishnanraman is right here. add trait Abelian and mix it in to the appropriate monoids. This works, for example:

trait Abelian

trait Monoid[T] {
  def zero: T
  def plus(l: T, r: T): T
}

class StringMonoid extends Monoid[String] {
  def zero = ""
  def plus(l: String, r: String) = l + r
}

class IntMonoid extends Monoid[Int] with Abelian {
  def zero = 0
  def plus(l: Int, r: Int) = l + r
}

object Monoid {
  implicit val int: Monoid[Int] = new IntMonoid
  implicit val string: Monoid[String] = new StringMonoid

  def commutes[T](implicit m: Monoid[T]) =
    m match {
      case _: Abelian => true
      case _ => false
    }

  def plus[T](l: T, r: T)(implicit m: Monoid[T]) = {
    if (commutes[T])
      m.plus(r, l)
    else
      m.plus(l, r)
  }
}

from algebird.

krishnanraman avatar krishnanraman commented on July 17, 2024

Perhaps now is a good time to add Oscar's Movember challenge problem into Algebird. https://gist.github.com/krishnanraman/4166029
That code defines "a" cyclic group of order n ( all cyclic groups are abelian ), with a specified zero.
( Note: Abelian groups aren't unique, which is why the "a", not "the". As I recall, there was some $50 movember bet about coding up Cayley tables for a cyclic group.)

from algebird.

aaron-siegel avatar aaron-siegel commented on July 17, 2024

I strongly prefer "Commutative" rather than "Abelian". The term "Abelian" is ordinarily reserved for groups - commutative semigroups and monoids are just called "Commutative Semigroups" and "Commutative Monoids". (e.g., Grillet: http://www.amazon.com/Commutative-Semigroups-Advances-Mathematics-Grillet/dp/1441948570/ref=sr_1_1?ie=UTF8&qid=1361313759&sr=8-1&keywords=grillet+semigroups)

To me, it would seem incredibly odd to say "extends Monoid[T] with Abelian". I think the most natural approach is something like the following:

class MyMonoid extends Monoid[T] with CommutativeSemigroup { /* ... */ }

where CommutativeSemigroup is a marker trait:

trait CommutativeSemigroup

the reason for calling it CommutativeSemigroup rather than Commutative is that we also (presumably) want commutative ring support. Thus Ring becomes

trait Ring[T] extends Group[T] with CommutativeSemigroup

(the additive group of a ring is always Abelian)

and another marker trait

trait CommutativeRing

identifies commutative multiplication operations. (and of course Fields are always CommutativeRings.)

Here's another proposal, which I think has a lot to recommend it: a whole range of marker traits in the expected hierarchy:

trait CommutativeSemigroup[T] extends Semigroup[T]
trait CommutativeMonoid[T] extends Monoid[T] with CommutativeSemigroup[T]
trait AbelianGroup[T] extends Group[T] with CommutativeMonoid[T]
trait Ring[T] extends AbelianGroup[T] { /* Ring body is just as before */ }
trait CommutativeRing[T] extends Ring[T]
trait Field[T] extends CommutativeRing[T] { /* Field body is just as before */ }

Then I can write

class MyMonoid[T] extends CommutativeMonoid[T] { /* My implementation */ }

which is quite natural.

I like the other ideas in Sam's comment, which are interchangeable with either proposal suggested here.

from algebird.

aaron-siegel avatar aaron-siegel commented on July 17, 2024

Btw, I should add that the proposed IsNotCommutative trait doesn't sit well with me at all. Monoids that lack inverses for their elements aren't (and shouldn't be) tagged with an IsNotGroup trait... and in general it seems cumbersome to annotate structures with tags for properties that they lack. The benefit of IsNotCommutative is to facility the CommutativeStatus pattern, which I don't like either - I really think tagging traits are the way to go.

The only disadvantage (relative to CommutativeStatus) is that we lose the ability to define structures that have some (but not all) commutative instances. But I think such cases are best handled hierarchically anyway... in my view we should take advantage of the fact that scala makes it easy to do this the right way.

from algebird.

krishnanraman avatar krishnanraman commented on July 17, 2024
case class Zn(order:Int, zero:Int) extends Abelian {
   def identity = zero
   def size = order
   def elements =  (1 to order).toSeq
   def cayley = {
      Vector.tabulate(order,order)((x,y)=> {
           val idx = math.abs(zero - (x+1)) // difference between x & zero
           val timesToShift = if ((x+1)>=zero) idx else (order-idx)
           val row = shift(elements, timesToShift )
           row(y)
      })
   }
   private def shift(s:Seq[Int], pos:Int) = {
      val n = 1+s.indexOf(pos)
      s.slice(n,s.size)++s.slice(0,n)
   }

   def plus(x:Int, y:Int) = cayley(x-1)(y-1)
   def inverse(x:Int) = cayley(x-1).indexOf(zero)+1
}

Works as advertised. Please cut-n-paste in repl & play with it. eg. On group of order 7 with 5 as zero, 1+1 = 4, and the inverse of 1 is 2.

scala> Zn(7,5)
res9: Zn = Zn(7,5)
scala> res9.plus(1,1)
res10: Int = 4
scala> res9.inverse(1)
res11: Int = 2

from algebird.

mikegagnon avatar mikegagnon commented on July 17, 2024

Regarding type-class vs. marker trait, I vote for the marker trait. Here's the pros and cons of using the marker trait as I see it:

pros: simple and our usage is consistent with marker-trait pattern
cons: it's not a type class, so if someone hasn't already defined FooMonoid as Commutative it could be pain. But our type hierarchy is shallow and we could add the marker trait throughout Algebird all at once pretty easily. Also, all checking for commutative must be done statically via type system (although, that could be considered a pro...)

Also, what do Albanians have to do with Monoids?

from algebird.

johnynek avatar johnynek commented on July 17, 2024

This is coming up in summingbird and I think we need to get something done.

The problem with a trait is that it doesn't recurse. For instance, Semigroup[Map[K, V]] is Commutative if Semigroup[V] is. With the typeclass approach, we can capture this, without, I don't know how to.

from algebird.

jcoveney avatar jcoveney commented on July 17, 2024

We have the money, we have the technology. Let's do this.

What are the reservations with the typeclass approach? More boilerplate? It seems like it more cleanly encapsulates the idea without baking things in, though @mikegagnon is correct in that the type hierarchy isn't so deep.

from algebird.

johnynek avatar johnynek commented on July 17, 2024

We should pick this up. I think @asiegel34's approach is the best one here (though I still think might suggest just CommutativeGroup instead of Abelian for consistency).

While we are at it, I'd go ahead and add Rng and Rig for the cases without identity and negation respectively. Then

trait Rng[T] extends Group[T] {
  def times(l: T, r: T): T
}

trait Rig[T] extends Monoid[T] {
  def times(l: T, r: T)
  def one: T
}

trait Ring[T] extends Rng[T] with Rig[T] with CommutativeGroup[T]

// useful in concurrent/distributed settings:
// http://en.wikipedia.org/wiki/Semilattice
// idempotent commutative semigroup is a semilattice (e.g. max, min)
trait Semilattice[T] extends CommutativeSemigroup[T]
// zero is either the smallest or largest item depending on if this is a meet or join semilattice.
trait BoundedSemilattice[T] extends CommutativeMonoid[T]

from algebird.

isnotinvain avatar isnotinvain commented on July 17, 2024

+1 to @asiegel34's approach, as well as Rng, Rig, etc. We might as well express as much as we can in the type hierarchy.

from algebird.

avibryant avatar avibryant commented on July 17, 2024

https://github.com/non/algebra is strugging with this same issue right now, we might want to make sure to coordinate. (Sounds like they're ending up with isCommutative instead).

from algebird.

johnynek avatar johnynek commented on July 17, 2024

Actually Avi, I think algebra has both runtime and compile time info. Which is good I think (you can always check the type so runtime is always open to you).

I am 90% in favor of using algebra, but I would like to see a more rigorous policy for how code gets in.

from algebird.

sritchie avatar sritchie commented on July 17, 2024

@johnynek , I propose that we close this since we're adopting shared typeclasses soon.

from algebird.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.