From Martin Odersky's Scala course I have the following Exercise (this a video exercise in which answer is given):
" Provide an implementation of the abstract class Nat that represents non-negative integers
Do not use standard numerical classes in this implementation. Rather, implement a sub-object and a sub-class.
One for the number zero, the other for strictly prositive numbers. "
Here is the code :
abstract class Nat {
def isZero : scala.Boolean
def predecessor : Nat
def successor = new Succ(this)
def + (that : Nat) : Nat
def - (that : Nat) : Nat
}
object Zero extends Nat {
def isZero = true
def predecessor = throw new Error("0.predecessor")
def + (that: Nat) = that
def - (that: Nat) = if(that.isZero) this else throw new Error("negative number")
}
class Succ(n : Nat) extends Nat {
def isZero = false
def predecessor = n
def +(that : Nat) = new Succ(n + that)
def -(that: Nat) = n - that.predecessor
}
Within a Scala worksheet I have :
object NatTests {
new Successor(Zero).+(new Successor(Zero))
}
Which returns a new Sucessor. I don't think I'm understanding this code fully as I should be able to add non zero objects without extending the code ? If so, how is this accomplished ?
You are able to add non zero numbers / objects without extending any of the classes Nat
, Zero
, or Succ
. When you use an object natObj
of type Nat
and construct a new object new Succ(natObject)
that new object represents a number that is one higher than the number that natObj
represents.
Maybe being able to view the objects, makes this a bit clearer:
abstract class Nat {
def isZero : Boolean
def predecessor : Nat
def successor = new Succ(this)
def + (that : Nat) : Nat
def - (that : Nat) : Nat
}
object Zero extends Nat {
def isZero = true
def predecessor = throw new Error("0.predecessor")
def + (that: Nat) = that
def - (that: Nat) = if(that.isZero) this else throw new Error("negative number")
override def toString = "0 => Zero"
}
class Succ(n : Nat) extends Nat {
def isZero = false
def predecessor = n
def + (that : Nat) = new Succ(n + that)
def - (that: Nat) = if (that.isZero) this else n - that.predecessor
override def toString = {
def findNumber(nat: Nat): Int =
if (nat.isZero) 0
else 1 + findNumber(nat.predecessor)
val number = findNumber(this)
String.valueOf(number) + " => " +
((1 to number) fold ("Zero")) ( (s,_) => "Succ(" + s + ")")
}
}
Now your Scala worksheet will show you the number an object represents and its internal structure:
object NatTests extends App {
val nat0 = Zero
val nat1 = new Succ(Zero)
val nat2 = new Succ(nat1) // or new Succ(new Succ(Zero))
val nat3 = new Succ(nat2) // or new Succ(new Succ(new Succ(Zero)))
println(nat0) //> 0 => Zero
println(nat1) //> 1 => Succ(Zero)
println(nat2) //> 2 => Succ(Succ(Zero))
println(nat3) //> 3 => Succ(Succ(Succ(Zero)))
println(nat2 + nat2) //> 4 => Succ(Succ(Succ(Succ(Zero))))
println(nat3 + nat2) //> 5 => Succ(Succ(Succ(Succ(Succ(Zero)))))
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With