Skip to content

Instantly share code, notes, and snippets.

@jpablo
Created December 8, 2016 09:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpablo/6ac08f5a7d7eaeab0e6e97a9e9db877b to your computer and use it in GitHub Desktop.
Save jpablo/6ac08f5a7d7eaeab0e6e97a9e9db877b to your computer and use it in GitHub Desktop.
SICP 2.1.1: Data Abstraction
data Ind = Fst | Snd
type Tup t = Ind -> t
cons x y Fst = x
cons x y Snd = y
fst' z = z Fst
snd' z = z Snd
makeRat = cons
numer = fst'
denom = snd'
equalRat :: (Num t, Eq t) => Tup t -> Tup t -> Bool
equalRat x y = numer x * denom y == numer y * denom x
addRat :: Num t => Tup t -> Tup t -> Tup t
addRat x y = makeRat ((numer x * denom y) + (numer y * denom x)) (denom x * denom y)
subRat :: Num t => Tup t -> Tup t -> Tup t
subRat x y = makeRat ((numer x * denom y) - (numer y * denom x)) (denom x * denom y)
print' :: Show t => Tup t -> String
print' z = show (numer z) ++ " / " ++ show (denom z)
package Chap2
import scala.language.higherKinds
trait AbstractTypes {
type Rational[A]
def makeRat[A](x: A, y: A): Rational[A]
def numer[A](r: Rational[A]): A
def denom[A](r: Rational[A]): A
}
trait AbstractOps extends AbstractTypes {
def equalRat[A](x: Rational[A], y: Rational[A])(implicit numeric: Numeric[A]): Boolean = {
import numeric._
numer(x) * denom(y) == numer(y) * denom(x)
}
def addRat[A](x: Rational[A], y: Rational[A])(implicit numeric: Numeric[A]): Rational[A] = {
import numeric._
makeRat(numer(x) * denom(y) + numer(y) * denom(x), denom(x) * denom(y))
}
}
object RationalsAsTuples extends AbstractOps {
type Rational[A] = (A,A)
def makeRat[A](x: A, y: A) = (x,y)
def numer[A](r: (A, A)): A = r._1
def denom[A](r: (A, A)): A = r._2
}
object TuplesAsFunctions extends AbstractOps {
sealed trait Ind
object Fst extends Ind
object Snd extends Ind
type Rational[A] = Ind => A
def cons[A](x: A, y: A) = (i: Ind) => i match {
case Fst => x
case Snd => y
}
def fst[A](z: Rational[A]) = z(Fst)
def snd[A](z: Rational[A]) = z(Snd)
def makeRat[A](x: A, y: A) = cons(x,y)
def numer[A](r: Rational[A]) = fst(r)
def denom[A](r: Rational[A]) = snd(r)
type Rat = Rational[Int]
def printRat(x: Rat) = s"${numer(x)} / ${denom(x)}"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment