effect-core-patterns
Use when Effect core patterns including Effect<A, E, R> type, succeed, fail, sync, promise, and Effect.gen for composing effects. Use for basic Effect operations.
What this skill does
# Effect Core Patterns
Master the core Effect patterns for building type-safe, composable applications
with Effect. This skill covers the Effect type, constructors, and composition
patterns using Effect.gen.
## The Effect Type
The Effect type has three type parameters:
```typescript
Effect<Success, Error, Requirements>
```
- **Success (A)**: The type of value that an effect can succeed with
- **Error (E)**: The expected errors that can occur (use `never` for no errors)
- **Requirements (R)**: The contextual dependencies required (use `never` for no dependencies)
```typescript
import { Effect } from "effect"
// Effect that succeeds with number, never fails, no requirements
const simpleEffect: Effect.Effect<number, never, never> = Effect.succeed(42)
// Effect that can fail with string error
const failableEffect: Effect.Effect<number, string, never> =
Effect.fail("Something went wrong")
// Effect that requires a UserService
interface UserService {
getUser: (id: string) => Effect.Effect<User, DbError, never>
}
const effectWithDeps: Effect.Effect<User, DbError, UserService> =
Effect.gen(function* () {
const userService = yield* Effect.service(UserService)
const user = yield* userService.getUser("123")
return user
})
```
## Creating Effects
### Effect.succeed - Always Succeeds
Use when you have a pure value and need an Effect:
```typescript
import { Effect } from "effect"
const result = Effect.succeed(42)
// Effect<number, never, never>
const user = Effect.succeed({ id: "1", name: "Alice" })
// Effect<User, never, never>
// Void effect (produces no useful value)
const voidEffect = Effect.succeed(undefined)
// Effect<void, never, never>
```
### Effect.fail - Expected Failure
Use for recoverable, expected errors:
```typescript
import { Effect } from "effect"
interface ValidationError {
_tag: "ValidationError"
message: string
}
const validateAge = (age: number): Effect.Effect<number, ValidationError, never> => {
if (age < 0) {
return Effect.fail({
_tag: "ValidationError",
message: "Age must be positive"
})
}
return Effect.succeed(age)
}
// Usage with Effect.gen
const program = Effect.gen(function* () {
const age = yield* validateAge(-5) // This will fail
return age
})
```
### Effect.sync - Synchronous Side Effects
Use for synchronous operations with side effects:
```typescript
import { Effect } from "effect"
// Reading from a mutable variable
let counter = 0
const incrementCounter = Effect.sync(() => {
counter++
return counter
})
// Logging
const log = (message: string) =>
Effect.sync(() => {
console.log(message)
})
// Current timestamp
const now = Effect.sync(() => Date.now())
// IMPORTANT: The function should not throw
// Thrown errors become "defects" (unexpected failures)
```
### Effect.try - Synchronous Operations That May Fail
Use for sync operations that might throw:
```typescript
import { Effect } from "effect"
// Parse JSON safely
const parseJSON = (text: string): Effect.Effect<unknown, Error, never> =>
Effect.try(() => JSON.parse(text))
// With custom error mapping
interface ParseError {
_tag: "ParseError"
message: string
}
const parseJSONCustom = (text: string): Effect.Effect<unknown, ParseError, never> =>
Effect.try({
try: () => JSON.parse(text),
catch: (error) => ({
_tag: "ParseError",
message: error instanceof Error ? error.message : String(error)
})
})
// Usage
const program = Effect.gen(function* () {
const data = yield* parseJSON('{"name": "Alice"}')
return data
})
```
### Effect.promise - Async Operations (No Errors)
Use for promises that should never reject:
```typescript
import { Effect } from "effect"
// Delayed execution
const delay = (ms: number): Effect.Effect<void, never, never> =>
Effect.promise(() =>
new Promise<void>((resolve) => setTimeout(resolve, ms))
)
// Fetch with assumption it won't fail
const fetchData = (url: string): Effect.Effect<Response, never, never> =>
Effect.promise(() => fetch(url))
// IMPORTANT: If promise rejects, it becomes a "defect"
// Use Effect.tryPromise for operations that can fail
```
### Effect.tryPromise - Async Operations That May Fail
Use for promises that might reject:
```typescript
import { Effect } from "effect"
interface NetworkError {
_tag: "NetworkError"
message: string
statusCode?: number
}
const fetchUser = (id: string): Effect.Effect<User, NetworkError, never> =>
Effect.tryPromise({
try: async () => {
const response = await fetch(`/api/users/${id}`)
if (!response.ok) {
throw new Error(`HTTP ${response.status}`)
}
return response.json()
},
catch: (error) => ({
_tag: "NetworkError",
message: error instanceof Error ? error.message : String(error),
statusCode: error instanceof Error && 'status' in error
? (error as any).status
: undefined
})
})
// Simplified version (errors become UnknownException)
const fetchUserSimple = (id: string): Effect.Effect<User, UnknownException, never> =>
Effect.tryPromise(() => fetch(`/api/users/${id}`).then(r => r.json()))
```
### Effect.async - Callback-Based APIs
Use for wrapping callback-style APIs:
```typescript
import { Effect } from "effect"
// Wrap setTimeout
const sleep = (ms: number): Effect.Effect<void, never, never> =>
Effect.async<void>((resume) => {
const timeoutId = setTimeout(() => {
resume(Effect.succeed(undefined))
}, ms)
// Optional cleanup on interruption
return Effect.sync(() => {
clearTimeout(timeoutId)
})
})
// Wrap Node.js callback API
interface FileError {
_tag: "FileError"
message: string
}
const readFile = (path: string): Effect.Effect<string, FileError, never> =>
Effect.async<string, FileError>((resume) => {
fs.readFile(path, 'utf8', (error, data) => {
if (error) {
resume(Effect.fail({
_tag: "FileError",
message: error.message
}))
} else {
resume(Effect.succeed(data))
}
})
})
```
## Composing Effects with Effect.gen
Effect.gen allows you to write effect code using generator syntax:
```typescript
import { Effect } from "effect"
// Basic composition
const program = Effect.gen(function* () {
const a = yield* Effect.succeed(10)
const b = yield* Effect.succeed(20)
return a + b
})
// With error handling
const programWithErrors = Effect.gen(function* () {
const age = yield* validateAge(25)
const user = yield* createUser({ age })
return user
})
// Sequential operations
const fetchUserProfile = (userId: string) =>
Effect.gen(function* () {
const user = yield* fetchUser(userId)
const posts = yield* fetchPosts(user.id)
const comments = yield* fetchComments(user.id)
return { user, posts, comments }
})
// Using control flow
const processData = (data: unknown) =>
Effect.gen(function* () {
const validated = yield* validateData(data)
if (validated.type === "user") {
const user = yield* createUser(validated)
return { type: "user", user }
} else {
const post = yield* createPost(validated)
return { type: "post", post }
}
})
// Error handling with short-circuiting
const safeDivide = (a: number, b: number) =>
Effect.gen(function* () {
if (b === 0) {
yield* Effect.fail({ _tag: "DivideByZero" })
return // Explicit return for type narrowing
}
return a / b
})
```
## Running Effects
### Effect.runSync - Synchronous Execution
Use for effects with no async operations or requirements:
```typescript
import { Effect } from "effect"
const result = Effect.runSync(Effect.succeed(42))
// 42
// Throws if effect can fail
try {
Effect.runSync(Effect.fail("error"))
} catch (error) {
// Caught
}
// CANNOT use with async effects or requirements
// Effect.runSync(Effect.promise(() => fetch("..."))) // Runtime error!
```
### Effect.runPromise - Async Execution
Use for async effects wiRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.