Skip to content

Instantly share code, notes, and snippets.

@kryptt
Last active November 28, 2019 12:32
Show Gist options
  • Save kryptt/608225304ac575c09288433170622f60 to your computer and use it in GitHub Desktop.
Save kryptt/608225304ac575c09288433170622f60 to your computer and use it in GitHub Desktop.
no ifs profit
/*
* This file has the setup and boilerplate.
* how to calculate the pay for a teacher, and the fee for a student.
* how to find the student or teacher just from a name string, and a
* `List` of names.
*/
type Fee = Double
type Pay = Double
type Balance = Double
sealed trait Person
case class Student(name: String, teacher: Teacher) extends Person
case class Teacher(name: String, students: List[Person]) extends Person
def feeCalc: Student => Fee = _ match {
case Student(_, t) => 1.10 * payCalc(t) / t.students.length
}
def payCalc: Teacher => Pay = _.students.foldLeft(0.0){
case (pay, t:Teacher) => pay + 0.1 * payCalc(t)
case (pay, s:Student) => pay + 2.5
}
def feeBalance: Fee => Balance = identity
def payBalance: Pay => Balance = - _
//Not worrying about the data itself
val names: List[String] = List.empty
def findPerson(name: String): Option[Either[Student, Teacher]] = None
/*
* Lets write down some intermediate helpper functions;
* the information from the signatures (types) of these intermediate functions helps
* document the expected flow
*/
def calc: Either[Student, Teacher] => Either[Fee, Pay] =
feeCalc.choose(payCalc)
def balance: Either[Fee, Pay] => Balance =
feeBalance.choice(payBalance)
def calcBalance: Either[Student, Teacher] => Balance =
calc.andThen(balance)
def nameBalance: String => Option[Balance] =
findPerson(_).map(calcBalance)
// ------------- //
names.foldMap(nameBalance(_).orEmpty)
// res: Balance = 0.0
// ------------- //
/* this is how it would look like if we avoided the helpers */
names.foldMap(
findPerson(_).map(
feeCalc.choose(payCalc).andThen(feeBalance.choice(payBalance))
).orEmpty
)
// res: Balance = 0.0
// ------------- //
/*
* Lets write down some intermediate helpper functions;
* the information from the signatures (types) of these intermediate functions helps
* document the expected flow
*/
def calc: Either[Student, Teacher] => Either[Fee, Pay] =
feeCalc choose payCalc
def balance: Either[Fee, Pay] => Balance =
feeBalance choice payBalance
// ------------- //
names
.flatMap(findPerson)
.map(calc)
.foldMap(balance)
// res: Balance = 0.0
// ------------- //
/* this is how it would look like if we avoided the helpers */
names
.flatMap(findPerson)
.map(feeCalc.choose(payCalc))
.foldMap(feeBalance.choice(payBalance))
// res: Balance = 0.0
@kryptt
Copy link
Author

kryptt commented Nov 28, 2019

A nice little note is that the merged functions iterates through the array only once, and releases the garbage it generates quicker...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment