mcpField
F
fp-ts-pragmatic

fp-ts-pragmatic

github.com/sickn33Development48.7k88 installsUpdated today
Repository

About fp-ts-pragmatic

A practical fp-ts guide for TypeScript developers, focused on functional patterns for nullable values, errors, and async operations. It also explains when simpler approaches are preferable.

Key features

  1. 01Practical nullable-value patterns
  2. 02Structure error handling
  3. 03Work with async operations
  4. 04Refactor imperative code functionally
  5. 05Identify cases to avoid FP

Use cases

  1. 01Get practical guidance when starting with fp-ts
  2. 02Organize TypeScript error handling
  3. 03Refactor asynchronous logic
  4. 04Decide whether code needs functional abstractions

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill fp-ts-pragmatic

After installing, type/fp-ts-pragmaticin Claude Code to confirm it loaded.

Bundled filesreferences/detailed-guide.md

Details

From the project README

Pragmatic Functional Programming

Read this first. This guide cuts through the academic jargon and shows you what actually matters. No category theory. No abstract nonsense. Just patterns that make your code better.

Detailed Guide

Read the detailed guide before executing this skill. It retains the complete procedure and reference material. Treat its safety, prerequisites, and validation requirements as mandatory. For focused work, load the relevant sections; for end-to-end work, read the guide completely.

When to Use This Skill

  • When starting with fp-ts and need practical guidance
  • When writing TypeScript code that handles nullable values, errors, or async operations
  • When you want cleaner, more maintainable functional code without the academic overhead
  • When refactoring imperative code to functional style

When NOT to Use FP

Functional programming is not always the answer. Here's when to keep it simple.

Simple Null Checks
// Just use optional chaining - it's built into the language
const city = user?.address?.city ?? 'Unknown'

// DON'T overcomplicate it
const city = pipe(
  O.fromNullable(user),
  O.flatMap(u => O.fromNullable(u.address)),
  O.flatMap(a => O.fromNullable(a.city)),
  O.getOrElse(() => 'Unknown')
)
Simple Loops
// A for loop is fine when you need early exit or complex logic
function findFirst(items: Item[], predicate: (i: Item) => boolean): Item | null {
  for (const item of items) {
    if (predicate(item)) return item
  }
  return null
}

// DON'T force FP when it doesn't help
const result = pipe(
  items,
  A.findFirst(predicate),
  O.toNullable
)
Performance-Critical Code
// For hot paths, benchmark both implementations on the actual runtime
function sumLarge(numbers: number[]): number {
  let sum = 0
  for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i]
  }
  return sum
}

// A.reduce does not create an intermediate array per item; callbacks still have runtime costs
const sum = pipe(numbers, A.reduce(0, (acc, n) => acc + n))
When Your Team Doesn't Know FP

If you're the only one who can read the code, it's not good code.

// If your team knows this pattern
async function getUser(id: string): Promise<User | null> {
  try {
    const response = await fetch(`/api/users/${encodeURIComponent(id)}`)
    if (!response.ok) return null
    return await response.json()
  } catch {
    return null
  }
}

// Don't force this on them
const getUser = (id: string): TE.TaskEither<Error, User> =>
  pipe(
    TE.tryCatch(() => fetch(`/api/users/${encodeURIComponent(id)}`), E.toError),
    TE.flatMap(r => r.ok ? TE.right(r) : TE.left(new Error('Not found'))),
    TE.flatMap(r => TE.tryCatch(() => r.json(), E.toError))
  )

Limitations

  • Use this skill only when the task clearly matches the scope described above.
  • Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
  • Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.

Comments

Markdown supported