diff --git a/README.md b/README.md index b97a2d668..7c3c59b91 100644 --- a/README.md +++ b/README.md @@ -463,7 +463,7 @@ val b: Result[Throwable, Int] = KyoApp.Unsafe.runAndBlock(2.minutes)(a) ``` -### Displaying Kyo type +### Displaying Kyo types Due to the extensive use of opaque types in Kyo, logging Kyo values can lead to confusion, as the output of `toString` will often lead out type information we are used to seeing in boxed types. For instance, when a pure value is lifted to a pending computation, you will only see the value if you call `.toString`: @@ -472,20 +472,36 @@ import kyo.* val a: Int < Any = 23 println(s"Kyo effect: $a") -// Ouputs `Kyo effect: 23` to console +// Ouput: Kyo effect: 23 ``` -This can be jarring to new Kyo users, since we would expect a Kyo computation to be something more than just a pure value. However, Kyo's ability to treat pure values as effects is part of what makes it so performant. Nevetheless, the string representations can mislead us as to the compiletime type of a value, which can make it harder to interpret our logs. To make this a bit easier, Kyo provides a string interpolator which will format Kyo types appropriately. To use this interpolater, prefix your interpolated strings with `k` instead of `s`. +This can be jarring to new Kyo users, since we would expect a Kyo computation to be something more than just a pure value. However, Kyo's ability to treat pure values as effects is part of what makes it so performant. Nevetheless, the string representations can mislead us as to the compiletime type of a value, which can make it harder to interpret our logs. To make things clearer, Kyo provides a `Show` utility to generate clearer string representation of types. ```scala import kyo.* val a: Int < Any = 23 -println(k"Kyo effect: $a") -// Ouputs `Kyo effect: Kyo(23)` to console + +val aStr: String = Show.show(a) + +println(s"Kyo effect: $aStr") +// Output: Kyo effect: Kyo(23) +``` + +We can still see the pure value (23) in the output, but now we can also see that it is a `Kyo`. This will work similarly for other unboxed types like `Maybe` and `Result` (see below). + +Converting values using `Show` directly can be cumbersome, however, so Kyo also provides a string interpolator to construct properly formatted strings automatically. To use this interpolater, prefix your interpolated strings with `k` instead of `s`. + +```scala +import kyo.* + +val a: Int < Any = 23 + +println(k"Kyo effect: $a, Kyo maybe: ${Maybe(23)}") +// Output: Kyo effect: Kyo(23), Kyo maybe: Present(23) ``` -We can still see the pure value (23) in the output, but now we can also see that it is a `Kyo`. This will work similarly for other unboxed types like `Maybe` and `Result` (see below). We recommend using `k` as the default string interpolator in Kyo applications for the best developer experience. +We recommend using `k` as the default string interpolator in Kyo applications for the best developer experience. ## Core Effects diff --git a/kyo-data/shared/src/test/scala/kyo/ShowTest.scala b/kyo-data/shared/src/test/scala/kyo/ShowTest.scala index 09aa1ab68..37297cf73 100644 --- a/kyo-data/shared/src/test/scala/kyo/ShowTest.scala +++ b/kyo-data/shared/src/test/scala/kyo/ShowTest.scala @@ -21,17 +21,25 @@ class ShowTest extends Test: "derivation" - { "should derive show for ADT correctly" in { assert(Show[ShowADT.Obj.type].show(ShowADT.Obj) == "Obj") + assert(Show.show(ShowADT.Obj) == "Obj") assert(Show[ShowADT].show(ShowADT.Obj) == "Obj") + assert(Show.show(ShowADT.Obj) == "Obj") val wr: Wr[Int] = Wr(23) assert(Show[ShowADT.Nested].show(ShowADT.Nested(wr)) == "Nested(Yep(23))") + assert(Show.show(ShowADT.Nested(wr)) == "Nested(Yep(23))") assert(Show[ShowADT].show(ShowADT.Nested(wr)) == "Nested(Yep(23))") + assert(Show.show(ShowADT.Nested(wr)) == "Nested(Yep(23))") } "should derive tuple correctly" in { assert(Show[EmptyTuple].show(EmptyTuple) == "EmptyTuple") + assert(Show.show(EmptyTuple) == "EmptyTuple") assert(Show[Tuple1[Wr[String]]].show(Tuple1(Wr("hello"))) == "(Yep(hello))") + assert(Show.show(Tuple1(Wr("hello"))) == "(Yep(hello))") assert(Show[(Int, Wr[String])].show((23, Wr("hello"))) == "(23,Yep(hello))") + assert(Show.show((23, Wr("hello"))) == "(23,Yep(hello))") assert(Show[(Int, Wr[String], Wr[Nothing])].show((23, Wr("hello"), Wr(null))) == "(23,Yep(hello),Nope)") + assert(Show.show((23, Wr("hello"), Wr(null))) == "(23,Yep(hello),Nope)") } }