1

Consider 2+7 == 3+6 (mod 5). Can you some how use scala syntactic sugar to achieve the same in scala code?

Keep in mind that 2+7 and 3+6 are regular scala Int so overriding the + or == to be mod 5 doesn't work. I'm actually interested in more complex congruences on algebras A. I could do A.congruent(a,b), and write that with some nice symbols like A.~(a,b), but I am interested in a == b (A) or a ==(A) b or perhaps A(a == b). Something where the congruence appears inbetween the terms a and b.

The bottom line of my struggles is that the congruence is defined for type A, and a,b are some elements passed to A but not actually of type A. E.g. A might be a group of matrices and the congruence is if individual matrices a and b differ by a scalar i.e. a*b^-1=sI_n. In particular, a, b will live inside of many groups and the congruence will change based on that. So I it isn't possible to simply add a reference within a and b back to A.

Some how the right solution seems to be the mathematical one, label the equivalence with A not the variables a and b. Yet scala syntactic sugar may not have such a sweetness in mind. Any suggestions appreciated.

Algeboy
  • 270
  • 2
  • 9
  • To clarify context, I'm happy for a solution that just tricks the REPL. If a user is writing their own actual code then prefix notation like `A.cong(a,b)` wont throw them. But students and teachers who don't code much would prefer infix style found in books. – Algeboy Jan 17 '18 at 05:25

2 Answers2

1

Try this:

implicit class ModEquals(a: Int) {
    def %%(n: Int) = new { def ===(b: Int) = (a - b) % n == 0 }
}

Usage:

7 %% 3 === 10

This solution enriches Ints with a %% method that takes the congruence. In this example, it's just modulu, but this can easily be extended to anything. The returned object is a class that has an === method defined to implements the equality check.

thesamet
  • 6,382
  • 2
  • 31
  • 42
  • Clever, the implicit class idea is the hint I needed, though it seems easier for my intention to replace `def %%` etc. with `def ~(b:Int) = (a-b)%n == 0`, so one can simply write `n=5; (2+7)~(4+10)` (true) and changing n, `n=7; (2+7)~(4+10)` false. And as @thesamet notes it adapts easily to generic congruences. Thanks! – Algeboy Jan 17 '18 at 16:29
0
import scala.languageFeature.implicitConversions
import scala.languageFeature.reflectiveCalls

case class ModuloArg(list: List[Int]) {
  assert(list.size > 1)

  def ==%%?(m: Int) = {
    val hm = list.head % m
    list.tail.filter(i => (i % m) != hm).isEmpty
  }

  def ::%%(n: Int) = ModuloArg(n :: list)

}

implicit class ModuloArgOps(i: Int) {
  def ::%%(n: Int) = ModuloArg(n :: i :: Nil)
}

Now, you can use these to check modulo equality,

// 4 == 10 (mod 3) 
scala> val mod3Equal4And10 = 4 ::%% 10 ==%%? 3
// mod3Equal4And10: Boolean = true

// 4 == 11 (mod 3) 
scala> val mod3Equal4And11 = 4 ::%% 11 ==%%? 3
//mod3Equal4And11: Boolean = false

// 4 == 10 == 13 == 16 (mod 3)
scala> val mod3Equal4And10And13And16 = 4 ::%% 10 ::%% 13 ::%% 16 ==%%? 3
// mod3Equal4And10And13And16: Boolean = true
sarveshseri
  • 13,738
  • 28
  • 47