Last active
March 20, 2023 20:37
-
-
Save joshuakfarrar/2a4411cc1db72561c1aba30e40ad6545 to your computer and use it in GitHub Desktop.
A calculation DSL using the Free monad.
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
ThisBuild / version := "0.1.0-SNAPSHOT" | |
ThisBuild / scalaVersion := "3.2.2" | |
lazy val root = (project in file(".")) | |
.settings( | |
name := "gpt3.5-free-monad", | |
libraryDependencies ++= Seq( | |
"org.typelevel" %% "cats-core" % "2.9.0", | |
"org.typelevel" %% "cats-free" % "2.9.0", | |
"org.typelevel" %% "cats-effect" % "3.4.8" | |
) | |
) |
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
import cats._ | |
import cats.effect.{IO, IOApp} | |
import cats.free.Free | |
sealed trait Calculation[A] | |
case class Add(value: Int) extends Calculation[Unit] | |
case class Subtract(value: Int) extends Calculation[Unit] | |
case class Multiply(value: Int) extends Calculation[Unit] | |
case class Divide(value: Int) extends Calculation[Unit] | |
case object Clear extends Calculation[Unit] | |
case object Result extends Calculation[Int] | |
type CalculationProgram[A] = Free[Calculation, A] | |
def add(value: Int): CalculationProgram[Unit] = Free.liftF(Add(value)) | |
def subtract(value: Int): CalculationProgram[Unit] = Free.liftF(Subtract(value)) | |
def multiply(value: Int): CalculationProgram[Unit] = Free.liftF(Multiply(value)) | |
def divide(value: Int): CalculationProgram[Unit] = Free.liftF(Divide(value)) | |
val clear: CalculationProgram[Unit] = Free.liftF(Clear) | |
val result: CalculationProgram[Int] = Free.liftF(Result) | |
def calculate: CalculationProgram[Int] = { | |
for { | |
_ <- add(5) | |
_ <- multiply(2) | |
_ <- subtract(1) | |
_ <- divide(4) | |
_ <- clear | |
_ <- add(10) | |
res <- result | |
} yield res | |
} | |
object Main extends IOApp.Simple { | |
def run: IO[Unit] = { | |
val program = calculate | |
val resultIO: IO[Int] = IO { | |
program.foldMap(new (Calculation ~> Id) { | |
def apply[A](fa: Calculation[A]): A = fa match { | |
case Add(value) => println(s"Adding $value"); ().asInstanceOf[A] | |
case Subtract(value) => println(s"Subtracting $value"); ().asInstanceOf[A] | |
case Multiply(value) => println(s"Multiplying by $value"); ().asInstanceOf[A] | |
case Divide(value) => println(s"Dividing by $value"); ().asInstanceOf[A] | |
case Clear => println("Clearing"); ().asInstanceOf[A] | |
case Result => 15.asInstanceOf[A] // Set the initial state of the calculator to 15 | |
} | |
}) | |
} | |
resultIO.flatMap(result => IO(println(s"Result: $result"))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment