Created
August 15, 2015 04:58
-
-
Save jackfarrington/d502d38bf3f8e28c601d to your computer and use it in GitHub Desktop.
Scala By Example exercise 6.0.3
This file contains hidden or 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
/* | |
* The trait Nat is provided by the text. | |
*/ | |
trait Nat { | |
def isZero: Boolean | |
def predecessor: Nat | |
def successor: Nat | |
def +(that: Nat): Nat | |
def -(that: Nat): Nat | |
// toInt is added for demonstration only and is not required by the implementation. | |
def toInt: Int | |
} | |
/* | |
* The object Zero is provided by the text. | |
*/ | |
object Zero extends Nat { | |
def isZero: Boolean = true | |
def predecessor: Nat = error("negative number") | |
def successor: Nat = new Succ(Zero) | |
def +(that: Nat): Nat = that | |
def -(that: Nat): Nat = if (that.isZero) Zero else error("negative number") | |
val toInt: Int = 0 | |
} | |
/* | |
* The class Succ is provided by the text. | |
*/ | |
class Succ(x: Nat) extends Nat { | |
def isZero: Boolean = false | |
def predecessor: Nat = x | |
def successor: Nat = new Succ(this) | |
def +(that: Nat): Nat = x + that.successor | |
def -(that: Nat): Nat = if (that.isZero) this else x - that.predecessor | |
val toInt: Int = x.toInt + 1 | |
} | |
/* | |
* Exercise 6.0.3 Write an implementation Integer of integer numbers. The implementation | |
* should support all operations of class Nat while adding two methods: | |
* | |
* def isPositive: Boolean | |
* def negate: Integer | |
* | |
* The first method should return true if the number is positive. The second method | |
* should negate the number. Do not use any of Scala’s standard numeric classes in your | |
* implementation. (Hint: There are two possible ways to implement Integer. One can | |
* either make use the existing implementation of Nat, representing an integer as a | |
* natural number and a sign. Or one can generalize the given implementation of Nat to | |
* Integer, using the three subclasses Zero for 0, Succ for positive numbers and Pred | |
* for negative numbers.) | |
*/ | |
/* | |
* Encapsulate the new sign behavior in a trait. | |
*/ | |
trait Sign { | |
def isPositive: Boolean | |
def negate: Sign | |
} | |
/* | |
* Indicates a positive sign value. | |
*/ | |
object Positive extends Sign { | |
def isPositive: Boolean = true | |
def negate: Sign = Negative | |
} | |
/* | |
* Indicates a negative sign value. | |
*/ | |
object Negative extends Sign { | |
def isPositive: Boolean = false | |
def negate: Sign = Positive | |
} | |
/* | |
* The Integer class wraps a natural number and optionally may take a sign. | |
*/ | |
case class Integer(value: Nat, sign: Sign = Positive) extends Nat with Sign { | |
def isZero: Boolean = value.isZero | |
def predecessor: Nat = | |
if (isZero) new Integer(value.successor, Negative) | |
else if (sign.isPositive) new Integer(value.predecessor, sign) | |
else new Integer(value.successor, Negative) | |
def successor: Nat = | |
if (isZero) new Integer(value.successor, Positive) | |
else if (sign.isPositive) new Integer(value.successor, sign) | |
else new Integer(value.predecessor, Negative) | |
def +(that: Nat): Nat = | |
if (isZero) that | |
else if (sign.isPositive) this.predecessor + that.successor | |
else this.successor + that.predecessor | |
def -(that: Nat): Nat = | |
if (that.isZero) this | |
else that match { | |
case Integer(v, s) => this + new Integer(v, s.negate) | |
} | |
def isPositive: Boolean = sign.isPositive | |
def negate: Integer = new Integer(value, sign.negate) | |
// The following two definitions are for demonstration only and are not required. | |
val toInt: Int = if (sign.isPositive) value.toInt else -value.toInt | |
override def toString = | |
"" + { if (this.isZero) "" else if (sign.isPositive) "+" else "-" } + value.toInt | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment