Created
October 17, 2013 11:38
-
-
Save v6ak/7023402 to your computer and use it in GitHub Desktop.
Scala coding Dojo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Ú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í. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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( | |
""" | |
|6yN8/btUBFsh21J/2oKYwgEkmXoGetHbzFs3f/xqttAyEmHiT1G4hU3Rjbo5qNVWG1ZIUHSEFFgn | |
|XsVW/Kq3ijwtdz2ntCxYLW5quRreLZJltfWmmPdkvAcZRwHVrLyXnFA1Du4BXJxZnNHq4fDSx+PP | |
|qAb9m4pvE6ZsRCcdb/EgLBHEdhrC03+Zeu1i6WqW23lngp0QUH0tYxutXMsxEPk9RM/UHIO/pUkY | |
|sngaapTcsY2tYPROd17dKpbMUkynp6xQXxxwUtUAEdQcfeWm/kepIIwOWiJ4q/o+oQJO2163JbFV | |
|veEzjM2rYu45XK1su7MU2f5hADycrSWtB0p/lWKToaQq4IcRhumdbc6h7msj8hsC6f8V8qxiTZ4G | |
|i4eJa2Og0Tq5CA2yK9cPROB1GAjglz1uKyHp1yu+7JP4fMHqXRYA77PB90/Zg5Jio3O6D+JQ0izC | |
|M0hiFV8RlhQXUXyXaANui9G+xUnZ686tK8ReIvURlQcE4x0XC++yFHdsJb1J0gO25GXdpqwEG+zt | |
|jcQ9UnzF6fQKO9YA7pdr8POv91R0nERLSyNF8YU+2cH7AKPycTAS8eU09zapZ8U6z8ODTN5zsCA2 | |
|4LIepebWtaU5NLmLguBT6JfONMKnscU4Hw66BgBSsC/EhakQm5/gUxPdQBKU0YmBrDOi3tCT5hyB | |
|RJhYfZjcPXU9lelkxWyQSj71dI59N1YBNL5A1VCVghEOKMWyGLok54AsNzaSdPIEQKWGx60SgsM5 | |
|OcAxnDxTjm8nf13gU1BAwks0+IVAgSDCiPXBK2u2RPUmAj4yLRlriWuag91cQ+UvM+c5ARo6wVbY | |
|tlksbDsTOOS3GOq38OWtcduL7Tjdj8nqunXDV2mDpA9RQvkrc6EG7wFeH5J31x5hmIrEyYAl1mH0 | |
|eQ2JjXcbGN2yBFrzN26Y0SThY/WlZHxnvaDCRWI2AUzYEw2MfA9yfAabR2M9HAfB4fBR/QziTnfd | |
|wgUJwBkMWq7uiHURxCZbBY/K5+pDvtM78XmJjbsKc4h9iSclecdw05sUh1Q749oF9vR/NySEa7In | |
|xRuVrk4lmiUM+1zUUjM3TJKNHBf9Dk1BaIZofrV8sMX+lRQc9eWMP74RcYZ3sVClmESiIZARFg3w | |
|CHC1SNd4AOXx/JRhrcnZndTLo7kBiyzHRD5UBOcsUZ6QSHgF0yayryT9vzLF4l8zuzmWdeq8Rdbh | |
|RtbJTdPQhVZ3kLkcn4chKbyDdMoTCwPZJgXzIgBScn97p0UUSJB8k9E8cMivyRZqmbPudAHLL8dL | |
|VwPifklF2jDRHiGzaBSVK7XFW0UWj+aMLOqoPZwIt+pZP8EV0IOmdn0JY5OdrNFrxWzwyqpjaWmD | |
|V0VKKwGWmPiYN1q5ZF+zZB7juMGe8ZQFJUSaN95VK5ZqFDsto+whnj/4paK9aVKNyHY+517yDFJ6 | |
|itii1S8a3RAn77mkp/SBgo6SaXdJp0sVkcHctD/HSirf+uMiXC+y1RsPLect2Oz1CGanCb8hJDfj | |
|4eHVaXsAOzm2E+JThA5dVY8APKAEDrj0fMWz3k2mKHD30ZFYR408L7HzPY/k1+M4qHg3H+IJkVVX | |
|EK5DyFNA5VaS10Usd/qrYc8WB24Hbu8aKKomXBSxpH46r905yvw1orXCjkdSyIufwswTKrGgOThq | |
|Br5YPpLT7yxlW6Z1QTHlhbCNlr6G85Y5Om6lA9vec5JGTRXk4G7SrINeNh8aU2bj9UWctkEuf6xJ | |
|Ca4pxcCbBXL6dHqReETrus7xcPezo/xNsr9AshBqZD1jDzElERb3VMNm7Lu2a4DAae8ABk+499Gn | |
|ghqaJFQr2C9eaV++mH3n+4Jc6GlXERTxn/x0ZrjiSr/zoGcQU6vF7scwycwvw8GGyW3Qj7k31gBy | |
|br5HdOsPmV1mSAnL6RDkgUYmFrt8yTZchVgNBlx5hWEVgNVsx5RG3UBrNGFzlG7/BGBb5W18UsVR | |
|m7Shc3jXSwIMItfVlTPYQqI0knYU/fflQp9/TqqTH2EJ2DjJsKHs1QuzkvI0gSMzO8Af9ZBaMZCz | |
|jCAC85/e0L8/8jcDPA9cMiRjPXbuq3aBtQJpfhD0oP0hHAOYKaG36F4UWVx0XpQYP8nwZwuQkVlr | |
|8+/4/voxMlw6u3VUdAQDv7OtDKlIlVRTqa8o+Mq7zY7spETx17xIgf2NI4hK9QA7fGEH0v9tYCvZ | |
|aZ0aHgaTwDJgUoo63o417tFJiTZbBkud5rW4bkMAUgtl/mrkEo3phZkbysE3umTBY+O+B4+9fygE | |
|3YiBBVdk76K1n6TgMUWhK18kCejaLZNm673X3NORIF6O6tmoYb/MUSm8Lj9PpHRY1cIM5/q3Io8j | |
|EReIlnF+cKG7LeSh9+lp+GOmZKBJwfDub7aoWqTS7h8k5HUnq68mtD6D0XPtPUt5aNETE9HsT4mz | |
|BtpS0S9U5AU6i4CyMNq5lSePJwTq84/JAyLJeGDEhWqEq1LJyQZHSrxbm2P42OdoAODMHdRq+/Ra | |
|rli4SaNemjuvama/vlTbza0SclEL8drB56fcl2aSNE4nOlLEoZT6mSJDZW2x/RCotxexWZYqienF | |
|nnH3yAY7Pi6bglIY5VCfkWW5C4n5QtYtBzMxQQaIDuuObENTc+Lvjth6GgYMMCASA+7eBgmD8oi0 | |
|2N0o9m1IW75YRdgJY0to5rtNlSTBonBX2Daws4RkfgRElZOOokbJp+uD2XD8717UWCLFCGvbKHOV | |
|HTpid6QnuBOqulJLWAnjuTGuFrIfkrNO/b4l6xOgZIe1f476WMWrQ+pRuq7GhMJ068Qmey6idRee | |
|9VyV5NlO0IXgQsWj/SBIQUJP0PT+/7craKEzWqHqDcTIoItMlZmutJkMflvud2oYShSgZspUZBAu | |
|CKnAgU/fqFcR6XL+We1JqRDwNgjEoHl/687bXWJqpC1u88AKVxuWazIQ+ILNrBGEjP2HJVFikULu | |
|nWHLozmS4CtbpEomEJBLHtmesowT4Tl5WeLSsE6WS/CU9aZ3aSDi4rjYz76pEHjJPZeJ8j7l7Hjm | |
|rRvLAk4z8ilLQJEI2bIYphS+dpss84aj9j2eM7h4SsGWBB7+SpqcOCH/1BZN82Qjf6QWsASWrE+m | |
| | |
""".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") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment