From a5139405bec15071e522310e6030301b7896dbc5 Mon Sep 17 00:00:00 2001
From: Thanh Nguyen <thanhnguyen2187@gmail.com>
Date: Mon, 26 Aug 2024 23:31:31 +0700
Subject: [PATCH 1/3] Add section "The flow method"

---
 .../100-essentials/600-pipeline.mdx           | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/content/docs/400-guides/100-essentials/600-pipeline.mdx b/content/docs/400-guides/100-essentials/600-pipeline.mdx
index 45dc23fdf..f19b3b479 100644
--- a/content/docs/400-guides/100-essentials/600-pipeline.mdx
+++ b/content/docs/400-guides/100-essentials/600-pipeline.mdx
@@ -531,6 +531,34 @@ const program = Effect.all([fetchTransactionAmount, fetchDiscountRate]).pipe(
 )
 ```
 
+## The flow method
+
+Sometimes, you may need to create a reusable pipeline of operations. In such
+cases, you can use the `flow` method.
+
+```ts twoslash
+import { Effect, Duration, flow } from "effect"
+
+const myRetryLogic = flow(
+  Effect.timeout(Duration.seconds(3)),
+  Effect.tapError((error) => Effect.log(`Failed: ${error}`)),
+  Effect.retry({ times: 2 }),
+  Effect.tapError((error) => Effect.log(`Abandon as retry failed: ${error}`)),
+)
+
+const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
+const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
+
+const fetchTransactionAmountWithRetry = fetchTransactionAmount.pipe(myRetryLogic)
+const fetchDiscountRateWithRetry = fetchDiscountRate.pipe(myRetryLogic)
+```
+
+<Info>
+    `flow` and `pipe` are very similar. The main difference is that `flow` returns *a function that returns an Effect*
+    (`() => Effect`), while `pipe` returns an `Effect`. It suggests that `pipe` should be used when you want a result,
+    while `flow` should be used for further composition.
+</Info>
+
 ## Cheatsheet
 
 Let's summarize the transformation functions we have seen so far:

From 5103d7c0a216f408ea6c6cf0f866a09ca5865acb Mon Sep 17 00:00:00 2001
From: Thanh Nguyen <thanhnguyen2187@gmail.com>
Date: Tue, 27 Aug 2024 00:54:22 +0700
Subject: [PATCH 2/3] Rearrange the whole document

---
 .../100-essentials/600-pipeline.mdx           | 101 +++++++++---------
 1 file changed, 52 insertions(+), 49 deletions(-)

diff --git a/content/docs/400-guides/100-essentials/600-pipeline.mdx b/content/docs/400-guides/100-essentials/600-pipeline.mdx
index f19b3b479..cd3ceccdd 100644
--- a/content/docs/400-guides/100-essentials/600-pipeline.mdx
+++ b/content/docs/400-guides/100-essentials/600-pipeline.mdx
@@ -60,6 +60,27 @@ In the above example, we start with an input value of `5`. The `increment` funct
 
 The result is equivalent to `subtractTen(double(increment(5)))`, but using `pipe` makes the code more readable because the operations are sequenced from left to right, rather than nesting them inside out.
 
+## flow
+
+`flow` is a "lazier" version of `pipe`. While `pipe` returns a concrete value, `flow` returns a function that returns a
+result. It allows us to reuse the same composed functions in different contexts.
+
+```ts twoslash
+import { pipe, flow } from "effect"
+
+const increment = (x: number) => x + 1
+const double = (x: number) => x * 2
+const subtractTen = (x: number) => x - 10
+
+const operation = flow(increment, double, subtractTen)
+
+const result1 = pipe(5, operation)
+const result2 = pipe(10, operation)
+
+console.log(result1) // Output: 2
+console.log(result2) // Output: 12
+```
+
 ## Functions vs Methods
 
 In the Effect ecosystem, libraries often expose functions rather than methods. This design choice is important for two key reasons: tree shakeability and extensibility.
@@ -447,62 +468,44 @@ Configuration: {"dbConnection":"localhost","port":8080}, DB Status: Connected to
 
 ## Build your first pipeline
 
-Now, let's combine `pipe`, `Effect.all` and `Effect.andThen` to build a pipeline that performs a series of transformations:
-
-```ts twoslash
-import { Effect, pipe } from "effect"
-
-// Function to add a small service charge to a transaction amount
-const addServiceCharge = (amount: number) => amount + 1
-
-// Function to apply a discount safely to a transaction amount
-const applyDiscount = (
-  total: number,
-  discountRate: number
-): Effect.Effect<number, Error> =>
-  discountRate === 0
-    ? Effect.fail(new Error("Discount rate cannot be zero"))
-    : Effect.succeed(total - (total * discountRate) / 100)
-
-// Simulated asynchronous task to fetch a transaction amount from a database
-const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
+Now, let's combine `pipe`, `Effect.all` and `Effect.andThen` to build a pipeline that performs a series of
+transformations.
 
-// Simulated asynchronous task to fetch a discount rate from a configuration file
-const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
+### Using pipe to chain operations
 
-// Assembling the program using a pipeline of effects
-const program = pipe(
-  Effect.all([fetchTransactionAmount, fetchDiscountRate]),
-  Effect.flatMap(([transactionAmount, discountRate]) =>
-    applyDiscount(transactionAmount, discountRate)
-  ),
-  Effect.map(addServiceCharge),
-  Effect.map((finalAmount) => `Final amount to charge: ${finalAmount}`)
-)
+At the beginning of this section, we saw how to use the `pipe` function to compose functions. Let us take a closer look
+on how to apply it to Effects. We should differentiate between
 
-// Execute the program and log the result
-Effect.runPromise(program).then(console.log) // Output: "Final amount to charge: 96"
-```
-
-## The pipe method
+- the `pipe` **method**, and
+- the `pipe` **function**
 
-Effect provides a `pipe` method that works similarly to the `pipe` method found in [rxjs](https://rxjs.dev/api/index/function/pipe). This method allows you to chain multiple operations together, making your code more concise and readable.
+by understanding that one comes from an Effect itself, while the other is a function that receives an input and applies
+other functions to it.
 
 Here's how the `pipe` **method** works:
 
 ```ts
+import { Effect } from "effect"
+
+// ---cut---
+const effect = Effect.succeed(5)
 const result = effect.pipe(func1, func2, ..., funcN)
 ```
 
-This is equivalent to using the `pipe` **function** like this:
+It is equivalent to using the `pipe` **function** like this:
 
 ```ts
+import { Effect, pipe } from "effect"
+
+// ---cut---
+const effect = Effect.succeed(5)
 const result = pipe(effect, func1, func2, ..., funcN)
 ```
 
-The `pipe` method is available on all effects and many other data types, eliminating the need to import the `pipe` function from the `Function` module and saving you some keystrokes.
+The `pipe` method is available on all effects and many other data types, eliminating the need to import the `pipe`
+function. It might save you some keystrokes occasionally.
 
-Let's rewrite the previous example using the `pipe` method:
+Let's finish the previous example using the `pipe` method:
 
 ```ts twoslash
 import { Effect } from "effect"
@@ -521,7 +524,6 @@ const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
 
 const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
 
-// ---cut---
 const program = Effect.all([fetchTransactionAmount, fetchDiscountRate]).pipe(
   Effect.flatMap(([transactionAmount, discountRate]) =>
     applyDiscount(transactionAmount, discountRate)
@@ -529,17 +531,18 @@ const program = Effect.all([fetchTransactionAmount, fetchDiscountRate]).pipe(
   Effect.map(addServiceCharge),
   Effect.map((finalAmount) => `Final amount to charge: ${finalAmount}`)
 )
+
+Effect.runPromise(program).then(console.log) // Output: "Final amount to charge: 96"
 ```
 
-## The flow method
+### Using flow to create reusable pipelines
 
-Sometimes, you may need to create a reusable pipeline of operations. In such
-cases, you can use the `flow` method.
+Sometimes, you may need to create a reusable pipeline of operations. In such cases, you can use the `flow` method.
 
 ```ts twoslash
 import { Effect, Duration, flow } from "effect"
 
-const myRetryLogic = flow(
+const customRetryLogic = flow(
   Effect.timeout(Duration.seconds(3)),
   Effect.tapError((error) => Effect.log(`Failed: ${error}`)),
   Effect.retry({ times: 2 }),
@@ -549,14 +552,14 @@ const myRetryLogic = flow(
 const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
 const fetchDiscountRate = Effect.promise(() => Promise.resolve(5))
 
-const fetchTransactionAmountWithRetry = fetchTransactionAmount.pipe(myRetryLogic)
-const fetchDiscountRateWithRetry = fetchDiscountRate.pipe(myRetryLogic)
+const fetchTransactionAmountWithRetry = fetchTransactionAmount.pipe(customRetryLogic)
+const fetchDiscountRateWithRetry = fetchDiscountRate.pipe(customRetryLogic)
 ```
 
 <Info>
-    `flow` and `pipe` are very similar. The main difference is that `flow` returns *a function that returns an Effect*
-    (`() => Effect`), while `pipe` returns an `Effect`. It suggests that `pipe` should be used when you want a result,
-    while `flow` should be used for further composition.
+    `flow` and `pipe` are very similar. The main difference is that `flow` returns *a function that returns a result*
+    (in this case, it is `() => Effect`), while `pipe` returns a result (an `Effect`). It suggests that `pipe` should be
+    used when you want a result, while `flow` should be used for further composition.
 </Info>
 
 ## Cheatsheet

From 579fc68455a7272d7e7135ad1dadaff47411bdbf Mon Sep 17 00:00:00 2001
From: Thanh Nguyen <thanhnguyen2187@gmail.com>
Date: Tue, 27 Aug 2024 01:38:29 +0700
Subject: [PATCH 3/3] Remove redundant cut

---
 content/docs/400-guides/100-essentials/600-pipeline.mdx | 2 --
 1 file changed, 2 deletions(-)

diff --git a/content/docs/400-guides/100-essentials/600-pipeline.mdx b/content/docs/400-guides/100-essentials/600-pipeline.mdx
index cd3ceccdd..5db3e4b6f 100644
--- a/content/docs/400-guides/100-essentials/600-pipeline.mdx
+++ b/content/docs/400-guides/100-essentials/600-pipeline.mdx
@@ -487,7 +487,6 @@ Here's how the `pipe` **method** works:
 ```ts
 import { Effect } from "effect"
 
-// ---cut---
 const effect = Effect.succeed(5)
 const result = effect.pipe(func1, func2, ..., funcN)
 ```
@@ -497,7 +496,6 @@ It is equivalent to using the `pipe` **function** like this:
 ```ts
 import { Effect, pipe } from "effect"
 
-// ---cut---
 const effect = Effect.succeed(5)
 const result = pipe(effect, func1, func2, ..., funcN)
 ```