The @effect/platform/Terminal module provides an abstraction for interacting with standard input and output, including reading user input and displaying messages on the terminal.
Basic Usage
The module provides a single Terminaltag, which serves as the entry point to reading from and writing to standard input and standard output.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
Reads a single line from the default standard input.
readLine
8
var console:Console
The console module provides a simple debugging console that is similar to the
JavaScript console mechanism provided by web browsers.
The module exports two specific components:
A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
A global console instance configured to write to process.stdout and
process.stderr. The global console can be used without importing the node:console module.
Warning: The global console object's methods are neither consistently
synchronous like the browser APIs they resemble, nor are they consistently
asynchronous like all other Node.js streams. See the note on process I/O for
more information.
Example using the global console:
console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(newError('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
// Error: Whoops, something bad happened
// at [eval]:5:15
// at Script.runInThisContext (node:vm:132:18)
// at Object.runInThisContext (node:vm:309:38)
// at node:internal/process/execution:77:19
// at [eval]-wrapper:6:22
// at evalScript (node:internal/process/execution:76:60)
// at node:internal/main/eval_string:23:3
constname='Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr
Example using the Console class:
constout=getStreamSomehow();
consterr=getStreamSomehow();
constmyConsole=new console.Console(out, err);
myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(newError('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err
Prints to stdout with newline. Multiple arguments can be passed, with the
first used as the primary message and all additional used as substitution
values similar to printf(3)
(the arguments are all passed to util.format()).
// timestamp=... level=INFO fiber=#0 message="Executing query: SELECT * FROM users"
// []
@since ― 2.0.0
provide(
import NodeTerminal
NodeTerminal.
constlayer:Layer<Terminal.Terminal, never, never>
@since ― 1.0.0
layer)))
12
// Input: "hello"
13
// Output: "input: hello"
Example: Number guessing game
This example demonstrates how to create a complete number-guessing game by reading input from the terminal and providing feedback to the user. The game continues until the user guesses the correct number.
Example (Interactive Number Guessing Game)
1
import {
import Terminal
Terminal } from"@effect/platform"
2
importtype {
typePlatformError=BadArgument|SystemError
@since ― 1.0.0
@since ― 1.0.0
PlatformError } from"@effect/platform/Error"
3
import {
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect,
import Option
@since ― 2.0.0
@since ― 2.0.0
Option,
import Random
Random } from"effect"
4
import {
import NodeRuntime
NodeRuntime,
import NodeTerminal
NodeTerminal } from"@effect/platform-node"
5
6
// Generate a secret random number between 1 and 100
@param ― string A string to convert into a number.
@param ― radix A value between 2 and 36 that specifies the base of the number in string.
If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
All other strings are considered decimal.
parseInt(
input: string
input, 10)
12
return
functionisNaN(number:number):boolean
Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).
@param ― number A numeric value.
isNaN(
constn:number
n) ||
constn:number
n<1||
constn:number
n>100?
import Option
@since ― 2.0.0
@since ― 2.0.0
Option.
constnone: <never>() =>Option.Option<never>
Creates a new Option that represents the absence of a value.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
@since ― 2.0.0
@since ― 2.0.0
Effect<
31
number,
32
import Terminal
Terminal.
classQuitException
A QuitException represents an exception that occurs when a user attempts to
quit out of a Terminal prompt for input (usually by entering ctrl+c).
@since ― 1.0.0
QuitException|
typePlatformError=BadArgument|SystemError
@since ― 1.0.0
@since ― 1.0.0
PlatformError,
33
import Terminal
Terminal.
interfaceTerminal
A Terminal represents a command-line interface which can read input from a
user and display messages to a user.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
// Check if the guess is too high, too low, or correct
45
const
constcheck: <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>) =>Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
check= <
function (typeparameter) Ain <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
A,
function (typeparameter) Ein <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
E,
function (typeparameter) Rin <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
R>(
46
secret: number
secret:number,
47
guess: number
guess:number,
48
ok: Effect.Effect<A, E, R>
ok:
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect.
interfaceEffect<outA, outE=never, outR=never>
The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
@since ― 2.0.0
@since ― 2.0.0
Effect<
function (typeparameter) Ain <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
A,
function (typeparameter) Ein <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
E,
function (typeparameter) Rin <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
R>,
49
ko: Effect.Effect<A, E, R>
ko:
import Effect
@since ― 2.0.0
@since ― 2.0.0
@since ― 2.0.0
Effect.
interfaceEffect<outA, outE=never, outR=never>
The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
@since ― 2.0.0
@since ― 2.0.0
Effect<
function (typeparameter) Ain <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
A,
function (typeparameter) Ein <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
E,
function (typeparameter) Rin <A, E, R>(secret:number, guess:number, ok:Effect.Effect<A, E, R>, ko:Effect.Effect<A, E, R>):Effect.Effect<A, PlatformError|E, Terminal.Terminal|R>
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
The Effect interface defines a value that lazily describes a workflow or
job. The workflow requires some context R, and may fail with an error of
type E, or succeed with a value of type A.
Effect values model resourceful interaction with the outside world,
including synchronous, asynchronous, concurrent, and parallel interaction.
They use a fiber-based concurrency model, with built-in support for
scheduling, fine-grained interruption, structured concurrency, and high
scalability.
To run an Effect value, you need a Runtime, which is a type that is
capable of executing Effect values.
@since ― 2.0.0
@since ― 2.0.0
Effect<
70
void,
71
import Terminal
Terminal.
classQuitException
A QuitException represents an exception that occurs when a user attempts to
quit out of a Terminal prompt for input (usually by entering ctrl+c).
@since ― 1.0.0
QuitException|
typePlatformError=BadArgument|SystemError
@since ― 1.0.0
@since ― 1.0.0
PlatformError,
72
import Terminal
Terminal.
interfaceTerminal
A Terminal represents a command-line interface which can read input from a
user and display messages to a user.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.
Delays the creation of an Effect until it is actually needed.
When to Use
Use suspend when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.
Details
suspend takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:
Lazy Evaluation: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
Handling Circular Dependencies: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
Unifying Return Types: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.
Provides a way to write effectful code using generator functions, simplifying
control flow and error handling.
When to Use
gen allows you to write code that looks and behaves like synchronous
code, but it can handle asynchronous tasks, errors, and complex control flow
(like loops and conditions). It helps make asynchronous code more readable
and easier to manage.
The generator functions work similarly to async/await but with more
explicit control over the execution of effects. You can yield* values from
effects and return the final result at the end.