Instantly share code, notes, and snippets.

# v6ak/Hello.scala Created Oct 17, 2013

What would you like to do?
Scala coding Dojo
 Úkoly z Functional programming in Scala - různé monoidy. (Co je to monoid: https://cs.wikipedia.org/wiki/Monoid ) U některých monoidů bylo zadání trošku otevřenější, člověk si musel vymyslet vlastní monoid, který splňuje nějaké podmínky. Zajímavé je ale spíše to testování.
 package com.czechscala.blank trait Monoid[A]{ def op(a1: A, a2: A): A def zero: A } object IntAddition extends Monoid[Int]{ def op(a1: Int, a2: Int):Int = a1+a2 def zero: Int = 0 } object IntMultiplication extends Monoid[Int]{ def op(a1: Int, a2: Int): Int = a1*a2 def zero: Int = 1 } object BooleanOr extends Monoid[Boolean]{ def op(a1: Boolean, a2: Boolean): Boolean = a1 || a2 def zero = false } object TrimMonoid extends Monoid[String]{ def op(a1: String, a2: String): String = a1.trim+" "+a2.trim def zero: String = "" } object Hello { def optionMonoid[T]: Monoid[Option[T]] = new Monoid[Option[T]] { //def op(a1: Option[T], a2: Option[T]) = a1 orElse a2 def op(a1: Option[T], a2: Option[T]) = a2 orElse a1 def zero = None } def endoMonoid[T]: Monoid[T => T] = new Monoid[(T) => T] { def op(a1: (T) => T, a2: (T) => T) = a1 andThen a2 def zero = identity } }
 package com.czechscala.blank import org.scalatest.FunSuite import Hello._ import org.scalatest.matchers.ShouldMatchers class HelloTest extends FunSuite with ShouldMatchers { type AssertEquals[T] = (T, T) => Unit def defaultAssert[T]: AssertEquals[T] = (left: T, right: T) => assert(left === right) def testNeutrality[T](monoid: Monoid[T])(value: T)(implicit eq: AssertEquals[T] = defaultAssert[T]){ eq(monoid.op(monoid.zero, value), value) eq(monoid.op(value, monoid.zero), value) } def testAssociativity[T](monoid: Monoid[T])(values: T*)(implicit eq: AssertEquals[T] = defaultAssert[T]){ require(values.size > 2) eq(values.foldLeft(monoid.zero)(monoid.op), values.foldRight(monoid.zero)(monoid.op)) } // Int addition test("int addition") { IntAddition.op(1, 3) should be (4) } test("int addition neutrality"){ -10 to 10 foreach testNeutrality(IntAddition) } test("int add assoc"){ testAssociativity(IntAddition)(2, 3, 4) testAssociativity(IntAddition)(3, 4, 5) } // int multiplication test("test IntMultiplication"){ assert(IntMultiplication.op(5, 6) === 30) } test("test multiplication neutrality"){ -10 to 10 foreach testNeutrality(IntMultiplication) } test("int mul assoc"){ testAssociativity(IntMultiplication)(2, 3, 4) testAssociativity(IntMultiplication)(3, 4, 5) } // boolean or test("Boolean or"){ assert(BooleanOr.op(false, false) === false) assert(BooleanOr.op(false, true) === true) assert(BooleanOr.op(true, false) === true) assert(BooleanOr.op(true, false) === true) } test("Boolean or neutrality"){ Seq(true, false) foreach testNeutrality(BooleanOr) } // Option monoid test("OptionMonoid"){ /* assert(optionMonoid[Int].op(Some(2), Some(3)) === Some(2)) assert(optionMonoid[Int].op(Some(2), None) === Some(2)) assert(optionMonoid[Int].op(None, Some(3)) === Some(3)) */ assert(optionMonoid[Int].op(Some(2), Some(3)) === Some(3)) assert(optionMonoid[Int].op(Some(2), None) === Some(2)) assert(optionMonoid[Int].op(None, Some(3)) === Some(3)) } test("OptionMonoid neutrality"){ -10 to 10 map {Some(_)} foreach testNeutrality(optionMonoid[Int]) Seq("a", "b", "xxx") map {Some(_)} foreach testNeutrality(optionMonoid[String]) } test("OptionMonoid associativity"){ testAssociativity(optionMonoid[Int])(Some(1), Some(2), Some(3)) testAssociativity(optionMonoid[Int])(None, Some(2), Some(3)) testAssociativity(optionMonoid[Int])(Some(1), None, Some(3)) testAssociativity(optionMonoid[Int])(Some(1), Some(2), None) testAssociativity(optionMonoid[Int])(Some(1), None, None) testAssociativity(optionMonoid[Int])(None, Some(2), None) testAssociativity(optionMonoid[Int])(None, None, Some(3)) testAssociativity(optionMonoid[Int])(None, None, None) } //def m(q: Int): Int => Int = q * _ //def a(q: Int): Int => Int = q + _ def compareFunctions[T](values: T*)(a: T=>T, b: T=>T){ for(value <- values){ assert(a(value) === b(value)) } } val compareIntFunctions: AssertEquals[Int => Int] = compareFunctions(-10 to 10 :_*)(_, _) val compareStringFunctions: AssertEquals[String => String] = compareFunctions( """ |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 | """.stripMargin.split('\n') :_*)(_, _) test("EndoMonoid"){ compareIntFunctions(endoMonoid[Int].op(2*, 3*), 6*) compareIntFunctions(endoMonoid[Int].op(2+, 3+), 5+) } test("EndoMonoid neutrality"){ testNeutrality(endoMonoid[Int])(2*)(compareIntFunctions) testNeutrality(endoMonoid[Int])(2+)(compareIntFunctions) } test("Endomonoid associativity"){ testAssociativity(endoMonoid[Int])(2*, 3+, 4*)(compareIntFunctions) testAssociativity(endoMonoid[String])(_.map(_+1 toChar), _.toLowerCase, _.replaceAll("a", "b"))(compareStringFunctions) } val compareStringsLoosely: AssertEquals[String] = (left, right) => assert(left.trim === right.trim) test("TrimMonoid"){ assert(TrimMonoid.op("a", "b") === "a b") assert(TrimMonoid.op(" a ", " b ") === "a b") assert(TrimMonoid.op("a ", "b ") === "a b") assert(TrimMonoid.op(" a x ", "b ") === "a x b") } test("Trim neutrality"){ testNeutrality(TrimMonoid)("a")(compareStringsLoosely) testNeutrality(TrimMonoid)(" a")(compareStringsLoosely) testNeutrality(TrimMonoid)(" a ")(compareStringsLoosely) } test("Trim associativity"){ testAssociativity(TrimMonoid)("dfsd", " dfsdf fgdfgd ", " gfdfg gfd gdf g df g", "gdfg fd gfd g fdftreterg") } }