diff --git a/index.html b/index.html index d422ccb..bccdc06 100644 --- a/index.html +++ b/index.html @@ -44,7 +44,7 @@
To use Terminus, add the following to your build.sbt
libraryDependencies += "org.creativescala" %% "terminus" % "0.27-70aadf7-SNAPSHOT"
+ libraryDependencies += "org.creativescala" %% "terminus" % "0.27-87472bb-SNAPSHOT"
Import Terminus
@@ -151,38 +151,38 @@type Program[A] = Terminal ?=> A
where Terminal
is a backend specific implementation that handles interfacing with the terminal. A Program
represents a function that, when run, will do something with the terminal.
Context functions are new to Scala 3, so many developers may not be familiar with how they work. There are three rules for working with them:
-If the compiler can tell that a context function is expected it will automatically create one. We can do this putting a Program
type annotation. Here are some examples
// Most of the methods on Terminal return programs
+ Context functions are new to Scala 3, so many developers may not be familiar with how they work. There are three rules for working with them, described below.
+ The first rule is that if the compiler can tell that a context function is expected it will automatically create one. We can do this with a Program
type annotation. Here are some examples
+ // Most of the methods on Terminal return programs
val aTerminalOperation: Program[Unit] = Terminal.write("Some text")
// Any expression can be a Program with a type annotation
val aProgram: Program[Int] = 1 + 1
-
If there is a given
value of the appropriate type in scope, any context functions will be automatically applied to that given
. This is what allows us to write effectful code in so-called direct-style, which just means writing normal code without monads or other complications. Here's an example that mixes effectful code, using the terminal, with some normal code. Notice that the entire result is a Program
. This type annotation means the compiler constructs a context function around the entire block.
val writeSomeStuff: Program[Unit] = {
-Terminal.write("Some output")
-// We can mix normal code in
-1 + 1
-Terminal.write("More output")
-Terminal.flush()
+ The second rule is that context functions will be automatically applied if there is a given
value of the appropriate type in scope. This is what allows us to write effectful code in so-called direct-style, which just means writing normal code without monads or other complications. Here's an example that mixes effectful code, using the terminal, with some normal code. Notice that the entire result is a Program
. This type annotation means the compiler constructs a context function around the entire block.
+ val writeSomeStuff: Program[Int] = {
+ Terminal.write("Some output")
+ // We can mix normal code in
+ val result = 1 + 1
+ Terminal.write("More output")
+ Terminal.flush()
+ result
}
- We can do the same thing with a method, by specifying the return type is a Program
. Here's an example.
- def doSomeStuff(): Program[Unit] = {
-Terminal.write("Some output")
-1 + 1
-Terminal.write("More output")
-Terminal.flush()
+ We can do the same thing with a method, by specifying the return type is a Program
. Here's an example.
+ def doSomeStuff(): Program[Int] = {
+ Terminal.write("Some output")
+ val result = 1 + 1
+ Terminal.write("More output")
+ Terminal.flush()
+ result
}
-
If we don't tell the compiler we're expecting a context function, we may get an error when the compiler attempts to apply a context function to a given value that does not exist.
-Terminal.write("Some output")
- The final rule is if we don't tell the compiler we're expecting a context function, we may get an error when the compiler attempts to apply a context function to a given value that does not exist.
+Terminal.write("Some output")
+// error:
+// No given instance of type terminus.effect.Writer was found for parameter of (terminus.effect.Writer) ?=> Unit
+ We can solve this by either adding a context function type annotation
+val ok: Program[Unit] = Terminal.write("Some output")
+ or by providing a given
value of the required type, which is what Terminal.run
does.
Terminal.run(Terminal.write("Some output"))
If you want to work directly with the terminal, without working with context functions, you can work with the types in terminus.effect
.