Skip to content

Commit

Permalink
apps simplification: move args to a protected method
Browse files Browse the repository at this point in the history
  • Loading branch information
fwbrasil committed Dec 9, 2023
1 parent 343f445 commit 449f447
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 36 deletions.
46 changes: 36 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,17 +99,39 @@ This unique property removes the need to juggle between `map` and `flatMap`. All
import kyo.options._
import kyo.tries._

// Kyo still supports both `map` and `flatMap`.
def example1(a: Int > Options, b: Int > Tries): Int > (Options with Tries) =
a.flatMap(v => b.map(_ + v))

// But using only `map` is recommended since it funcions like `flatMap` due to effect widening.
def example2(a: Int > Options, b: Int > Tries): Int > (Options with Tries) =
a.map(v => b.map(_ + v))
// Kyo still supports both `map`
// and `flatMap`.
def example1(
a: Int > Options,
b: Int > Tries
): Int > (Options with Tries) =
a.flatMap(v => b.map(_ + v))

// But using only `map` is recommended
// since it funcions like `flatMap` due
// to effect widening.
def example2(
a: Int > Options,
b: Int > Tries
): Int > (Options with Tries) =
a.map(v => b.map(_ + v))
```

The `map` method automatically updates the set of pending effects. When you apply `map` to computations that have different pending effects, Kyo reconciles these into a new computation type that combines all the unique pending effects from both operands.

When a computation produces a `Unit` value, Kyo also offers an `andThen` method for more fluent code:

```scala
// An example computation that
// produces 'Unit'.
val a: Unit > IOs =
IOs(println("hello"))

// Use 'andThen'.
val b: String > IOs =
a.andThen(IOs(println(" world")))
```

### Effect widening

Kyo's set of pending effects is a contravariant type parameter. This encoding permits computations to be widened to encompass a larger set of effects.
Expand Down Expand Up @@ -341,16 +363,20 @@ import kyo.resources._
import kyo.concurrent.fibers._

object MyApp extends App {
// Must return `Unit` and only use `Fibers`, `Resources`, `Consoles` and `Tries`.
// Only return pending `Fibers`, `Resources`, `Consoles` and `Tries`.
// Handle other effects like `Options` before returning.
def run(args: List[String]): Unit > (Fibers with Resources with Consoles with Tries) =
// The produced value can be of any type and is automatically
// printed to the console.
def run: String > (Fibers with Resources with Consoles with Tries) =
for {
_ <- Consoles.println("Starting the app...")
currentTime <- Clocks.now
_ <- Consoles.println(s"Current time is: $currentTime")
randomNumber <- Randoms.nextInt(100)
_ <- Consoles.println(s"Generated random number: $randomNumber")
} yield ()
} yield {
"example"
}
}
```

Expand Down
13 changes: 7 additions & 6 deletions kyo-core/shared/src/main/scala/kyo/apps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ object apps {

abstract class App {

// TODO initialization issues
private var _args: List[String] = List.empty
protected def args: List[String] = _args

final def main(args: Array[String]): Unit =
App.run(run(args.toList))(Flat.unsafe.checked)
final def main(args: Array[String]): Unit = {
_args = args.toList
App.run(run.map(Consoles.println(_)))(Flat.unsafe.checked)
}

def run(
args: List[String]
): Unit > (Fibers with Resources with Consoles with Tries)
def run: Any > (Fibers with Resources with Consoles with Tries)

}

Expand Down
30 changes: 16 additions & 14 deletions kyo-core/shared/src/test/scala/kyoTest/KyoAppTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,27 @@ import scala.concurrent.duration._
class AppTest extends KyoTest {

"args" in {
var args: List[String] = Nil
val app: App = (a: List[String]) => {
args = a
()
var _args: List[String] = Nil
val app = new App {
def run = IOs {
_args = args
}
}
app.main(Array("hello", "world"))
assert(args == List("hello", "world"))
assert(_args == List("hello", "world"))
}

"effects" in run {
val app: App = (a: List[String]) => {
for {
_ <- Timers.scheduleAtFixedRate(1.second, 1.second)(())
_ <- Randoms.nextInt
_ <- Consoles.println("1")
_ <- Clocks.now
_ <- Resources.ensure(())
_ <- Fibers.init(())
} yield ()
val app = new App {
def run =
for {
_ <- Timers.scheduleAtFixedRate(1.second, 1.second)(())
_ <- Randoms.nextInt
_ <- Consoles.println("1")
_ <- Clocks.now
_ <- Resources.ensure(())
_ <- Fibers.init(())
} yield ()
}
app.main(Array())
succeed
Expand Down
14 changes: 8 additions & 6 deletions kyo-llm/shared/src/main/scala/kyo/llm/apps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ object apps {

abstract class App {

final def main(args: Array[String]): Unit =
private var _args: List[String] = List.empty
protected def args: List[String] = _args

final def main(args: Array[String]): Unit = {
_args = args.toList
kyo.apps.App.run {
Requests.run {
AIs.run {
run(args.toList)
.map(Consoles.println(_))
run.map(Consoles.println(_))
}
}
}
}

def run(
args: List[String]
): Any > (kyo.apps.App.Effects with AIs)
def run: Any > (kyo.apps.App.Effects with AIs)
}
}

0 comments on commit 449f447

Please sign in to comment.