Effect Hello World

Let's come back to index.ts:

index.ts
import { Console, Effect } from "effect";

const main = Console.log("Hello world");

Effect.runSync(main);

This is the "Hello World" of effect, equivalent to console.log.

We can already notice the first major difference with effect programs: in effect defining the app (main) and executing it (Effect.runSync) are two separate actions.

We explicitly execute, meaning that effects don't run eagerly like console.log does!

/// 1️⃣ Define the `main` app
const main = Console.log("Hello world");

/// 2️⃣ Execute app
Effect.runSync(main);

Why is that?

An Effect is a description of a series of operations:

  • console.log executes some effect and returns void
  • Console.log only describes what will happen without executing any effect
/// 👇 `native` is `void`, the effect has already been executed!
/// This operation already "did" something!
const native: void = console.log("Hello world");

/// 👇 `effect` is `Effect<void>`, it describe something that when executed returns `void`
/// This only describes what should happen, it didn't do anything yet
const effect: Effect<void> = Console.log("Hello world");

Effect alone does not execute any logic. Instead, you need to explicitly call a run* method (in this example runSync).

This is similar to storing a function instead of executing it:

/// 1️⃣ Define the `main` app
const main = () => console.log("Hello World");

/// 2️⃣ Execute app (explicitly)
main();

Functional effects are immutable data structures that merely describe sequences of operations.

They have to be explicitly run to execute real effects.

How Console.log works

Console.log is a function that returns Effect<void>.

In practice this means that Console.log, when executed, returns void:

// 👇 Definition
const main: Effect<void> = Console.log("Hello world");

// 👇 Execution
Effect.runSync(main); // void

Again, this is similar to a function that when executed prints in the console:

type Program<T> = () => T;

// 👇 Definition
const main: Program<void> = () => console.log("Hello World");

// 👇 Execution
main(); // void

Effect.runSync takes as input an Effect and runs it synchronously.

Result: run a sync program that prints the string "Hello World" and returns void:

  • "run a sync program...": Effect.runSync
  • "...that prints the string "Hello World"...": Console.log("Hello World")
  • "...and returns void": Effect<void>
index.ts
import { Console, Effect } from "effect";

const main = Console.log("Hello world");

Effect.runSync(main);
> effect-getting-started-course@1.0.0 dev
> tsx src/index.ts

Hello world