[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ESZFQ5RAQ52Z2TECTDHCR0":3,"skill-same:01M6ESZFQ5RAQ52Z2TECTDHCR0":66},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":32,"linkOnly":33,"markdownContent":34,"markdownBody":35,"frontMatter":36,"refName":37,"commitSha":38,"skillDirectory":39,"forksCount":40,"repositoryHtmlUrl":41,"repositoryHomepageUrl":42,"ownerHtmlUrl":43,"ownerBlogUrl":6,"ownerDescription":44,"updatedAt":45,"install":46,"resources":59},"01M6ESZFQ5RAQ52Z2TECTDHCR0","functional-patterns",null,"Functional programming patterns that promote testability, composability, and maintainability.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Ffunctional-patterns\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[24,25,26,27,28,29,30,31],"patterns","functional","functional patterns","functional programming","promote","programming","maintainability","testability","2026-11-10 10:12:30",false,"---\nname: functional-patterns\ndescription: Functional programming patterns that promote testability, composability, and maintainability.\n---\n\n# Functional Patterns for Node.js\u002FTypeScript\n\n## Overview\nFunctional programming patterns that promote testability, composability, and maintainability.\n\n## Pure Functions\n\n### Definition\nA pure function:\n- Always returns the same output for the same input\n- Has no side effects (no I\u002FO, no mutation)\n\n### Examples\n\n```typescript\n\u002F\u002F Pure: Deterministic, no side effects\nconst add = (a: number, b: number): number => a + b;\n\nconst calculateTotal = (items: OrderItem[]): number =>\n  items.reduce((sum, item) => sum + item.price * item.quantity, 0);\n\nconst filterActiveUsers = (users: User[]): User[] =>\n  users.filter((user) => user.isActive);\n\n\u002F\u002F Impure: Has side effects\nconst saveUser = async (user: User): Promise\u003Cvoid> => {\n  await database.save(user); \u002F\u002F I\u002FO side effect\n};\n\nconst logMessage = (msg: string): void => {\n  console.log(msg); \u002F\u002F Side effect\n};\n\nconst generateId = (): string => {\n  return crypto.randomUUID(); \u002F\u002F Non-deterministic\n};\n```\n\n### Pure Core, Impure Shell\n\n```typescript\n\u002F\u002F Pure core - all business logic\nconst validateOrder = (order: Order): Result\u003COrder, ValidationError> => {\n  if (!order.items.length) return Result.fail({ code: 'EMPTY_ORDER' });\n  if (order.total \u003C 0) return Result.fail({ code: 'INVALID_TOTAL' });\n  return Result.ok(order);\n};\n\nconst calculateDiscount = (order: Order, user: User): number => {\n  const baseDiscount = user.isPremium ? 0.15 : 0;\n  const volumeDiscount = order.items.length > 10 ? 0.05 : 0;\n  return baseDiscount + volumeDiscount;\n};\n\nconst applyDiscount = (order: Order, discountRate: number): Order => ({\n  ...order,\n  total: order.total * (1 - discountRate),\n});\n\n\u002F\u002F Impure shell - handles I\u002FO\nconst processOrderHandler = (deps: Dependencies) => async (order: Order) => {\n  const validation = validateOrder(order);\n  if (validation.isFailure) return validation;\n\n  const user = await deps.userRepo.findById(order.userId); \u002F\u002F I\u002FO\n  const discount = calculateDiscount(validation.value, user);\n  const discounted = applyDiscount(validation.value, discount);\n\n  await deps.orderRepo.save(discounted); \u002F\u002F I\u002FO\n  await deps.notifier.send(user.email, 'Order confirmed'); \u002F\u002F I\u002FO\n\n  return Result.ok(discounted);\n};\n```\n\n## Immutability\n\n### Immutable Updates\n\n```typescript\n\u002F\u002F Bad: Mutation\nconst addItemToCart = (cart: Cart, item: Item) => {\n  cart.items.push(item);\n  cart.total += item.price;\n  return cart;\n};\n\n\u002F\u002F Good: Immutable update\nconst addItemToCart = (cart: Cart, item: Item): Cart => ({\n  ...cart,\n  items: [...cart.items, item],\n  total: cart.total + item.price,\n});\n\n\u002F\u002F Good: Nested immutable update\nconst updateUserAddress = (user: User, address: Partial\u003CAddress>): User => ({\n  ...user,\n  address: {\n    ...user.address,\n    ...address,\n  },\n});\n\n\u002F\u002F Good: Using readonly types\ntype ReadonlyUser = {\n  readonly id: string;\n  readonly email: string;\n  readonly addresses: readonly Address[];\n};\n\n\u002F\u002F Good: Immutable array operations\nconst addItem = \u003CT>(arr: readonly T[], item: T): readonly T[] => [...arr, item];\nconst removeAt = \u003CT>(arr: readonly T[], index: number): readonly T[] =>\n  arr.filter((_, i) => i !== index);\nconst updateAt = \u003CT>(arr: readonly T[], index: number, item: T): readonly T[] =>\n  arr.map((existing, i) => (i === index ? item : existing));\n```\n\n## Function Composition\n\n### Pipe and Compose\n\n```typescript\n\u002F\u002F Pipe: left to right\ntype Fn\u003CA, B> = (a: A) => B;\n\nconst pipe = \u003CA, B, C>(\n  f: Fn\u003CA, B>,\n  g: Fn\u003CB, C>\n): Fn\u003CA, C> => (a) => g(f(a));\n\nconst pipe3 = \u003CA, B, C, D>(\n  f: Fn\u003CA, B>,\n  g: Fn\u003CB, C>,\n  h: Fn\u003CC, D>\n): Fn\u003CA, D> => (a) => h(g(f(a)));\n\n\u002F\u002F Usage\nconst processInput = pipe3(\n  trim,\n  toLowerCase,\n  validateEmail\n);\n\n\u002F\u002F Variadic pipe\nconst pipeAll = \u003CT>(...fns: Array\u003C(x: T) => T>) =>\n  (initial: T): T => fns.reduce((acc, fn) => fn(acc), initial);\n\nconst processString = pipeAll(\n  (s: string) => s.trim(),\n  (s: string) => s.toLowerCase(),\n  (s: string) => s.replace(\u002F\\s+\u002Fg, '-')\n);\n```\n\n### Higher-Order Functions\n\n```typescript\n\u002F\u002F Function that returns a function\nconst withLogging = \u003CT extends (...args: any[]) => any>(fn: T) =>\n  (...args: Parameters\u003CT>): ReturnType\u003CT> => {\n    console.log('Calling with:', args);\n    const result = fn(...args);\n    console.log('Result:', result);\n    return result;\n  };\n\n\u002F\u002F Function that takes a function\nconst retry = \u003CT>(\n  fn: () => Promise\u003CT>,\n  attempts: number = 3\n): Promise\u003CT> =>\n  fn().catch((error) =>\n    attempts > 1 ? retry(fn, attempts - 1) : Promise.reject(error)\n  );\n\n\u002F\u002F Currying\nconst multiply = (a: number) => (b: number): number => a * b;\nconst double = multiply(2);\nconst triple = multiply(3);\n\n\u002F\u002F Partial application\nconst createLogger = (prefix: string) =>\n  (message: string): void => console.log(`[${prefix}] ${message}`);\n\nconst infoLog = createLogger('INFO');\nconst errorLog = createLogger('ERROR');\n```\n\n## Result Pattern (Monadic Error Handling)\n\n### Basic Result Type\n\n```typescript\ntype Result\u003CT, E> =\n  | { readonly _tag: 'Ok'; readonly value: T }\n  | { readonly _tag: 'Err'; readonly error: E };\n\nconst ok = \u003CT>(value: T): Result\u003CT, never> => ({ _tag: 'Ok', value });\nconst err = \u003CE>(error: E): Result\u003Cnever, E> => ({ _tag: 'Err', error });\n\nconst isOk = \u003CT, E>(result: Result\u003CT, E>): result is { _tag: 'Ok'; value: T } =>\n  result._tag === 'Ok';\n\nconst isErr = \u003CT, E>(result: Result\u003CT, E>): result is { _tag: 'Err'; error: E } =>\n  result._tag === 'Err';\n```\n\n### Result Operations\n\n```typescript\n\u002F\u002F Map: transform success value\nconst map = \u003CT, U, E>(\n  result: Result\u003CT, E>,\n  fn: (value: T) => U\n): Result\u003CU, E> =>\n  isOk(result) ? ok(fn(result.value)) : result;\n\n\u002F\u002F MapError: transform error value\nconst mapError = \u003CT, E, F>(\n  result: Result\u003CT, E>,\n  fn: (error: E) => F\n): Result\u003CT, F> =>\n  isErr(result) ? err(fn(result.error)) : result;\n\n\u002F\u002F FlatMap (chain): compose Result-returning functions\nconst flatMap = \u003CT, U, E>(\n  result: Result\u003CT, E>,\n  fn: (value: T) => Result\u003CU, E>\n): Result\u003CU, E> =>\n  isOk(result) ? fn(result.value) : result;\n\n\u002F\u002F Match: exhaustive handling\nconst match = \u003CT, E, R>(\n  result: Result\u003CT, E>,\n  handlers: { ok: (value: T) => R; err: (error: E) => R }\n): R =>\n  isOk(result) ? handlers.ok(result.value) : handlers.err(result.error);\n```\n\n### Chaining Results\n\n```typescript\ntype ValidationError = { field: string; message: string };\ntype ProcessingError = { code: string; details: string };\ntype AppError = ValidationError | ProcessingError;\n\nconst validateInput = (input: unknown): Result\u003CValidInput, ValidationError> => {\n  \u002F\u002F ...\n};\n\nconst processData = (input: ValidInput): Result\u003CProcessedData, ProcessingError> => {\n  \u002F\u002F ...\n};\n\nconst formatOutput = (data: ProcessedData): Output => {\n  \u002F\u002F ...\n};\n\n\u002F\u002F Compose the pipeline\nconst handleRequest = (input: unknown): Result\u003COutput, AppError> => {\n  const validated = validateInput(input);\n  if (isErr(validated)) return validated;\n\n  const processed = processData(validated.value);\n  if (isErr(processed)) return processed;\n\n  return ok(formatOutput(processed.value));\n};\n\n\u002F\u002F Or with flatMap\nconst handleRequestFunctional = (input: unknown): Result\u003COutput, AppError> =>\n  flatMap(validateInput(input), (valid) =>\n    map(processData(valid), formatOutput)\n  );\n```\n\n## Option\u002FMaybe Pattern\n\n```typescript\ntype Option\u003CT> =\n  | { readonly _tag: 'Some'; readonly value: T }\n  | { readonly _tag: 'None' };\n\nconst some = \u003CT>(value: T): Option\u003CT> => ({ _tag: 'Some', value });\nconst none: Option\u003Cnever> = { _tag: 'None' };\n\nconst isSome = \u003CT>(opt: Option\u003CT>): opt is { _tag: 'Some'; value: T } =>\n  opt._tag === 'Some';\n\nconst isNone = \u003CT>(opt: Option\u003CT>): opt is { _tag: 'None' } =>\n  opt._tag === 'None';\n\n\u002F\u002F Operations\nconst mapOption = \u003CT, U>(opt: Option\u003CT>, fn: (value: T) => U): Option\u003CU> =>\n  isSome(opt) ? some(fn(opt.value)) : none;\n\nconst getOrElse = \u003CT>(opt: Option\u003CT>, defaultValue: T): T =>\n  isSome(opt) ? opt.value : defaultValue;\n\nconst fromNullable = \u003CT>(value: T | null | undefined): Option\u003CT> =>\n  value != null ? some(value) : none;\n\n\u002F\u002F Usage\nconst findUser = (id: string): Option\u003CUser> => {\n  const user = users.find((u) => u.id === id);\n  return fromNullable(user);\n};\n\nconst getUserEmail = (id: string): string =>\n  getOrElse(\n    mapOption(findUser(id), (user) => user.email),\n    'unknown@example.com'\n  );\n```\n\n## Dependency Injection via Functions\n\n```typescript\n\u002F\u002F Define dependencies as a type\ntype Dependencies = {\n  userRepo: UserRepository;\n  orderRepo: OrderRepository;\n  logger: Logger;\n  clock: () => Date; \u002F\u002F Even time can be injected\n};\n\n\u002F\u002F Create service factory\nconst createOrderService = (deps: Dependencies) => ({\n  createOrder: async (data: CreateOrderData): Promise\u003CResult\u003COrder, OrderError>> => {\n    const user = await deps.userRepo.findById(data.userId);\n    if (!user) {\n      return err({ code: 'USER_NOT_FOUND', userId: data.userId });\n    }\n\n    const order: Order = {\n      id: generateId(),\n      ...data,\n      createdAt: deps.clock(),\n      status: 'pending',\n    };\n\n    deps.logger.info({ orderId: order.id }, 'Creating order');\n    await deps.orderRepo.save(order);\n\n    return ok(order);\n  },\n});\n\n\u002F\u002F Test with fake dependencies\ndescribe('OrderService', () => {\n  it('should create order', async () => {\n    const deps: Dependencies = {\n      userRepo: { findById: jest.fn().mockResolvedValue({ id: '1' }) },\n      orderRepo: { save: jest.fn() },\n      logger: { info: jest.fn() },\n      clock: () => new Date('2024-01-01'),\n    };\n\n    const service = createOrderService(deps);\n    const result = await service.createOrder({ userId: '1', items: [] });\n\n    expect(isOk(result)).toBe(true);\n  });\n});\n```\n","# Functional Patterns for Node.js\u002FTypeScript\n\n## Overview\nFunctional programming patterns that promote testability, composability, and maintainability.\n\n## Pure Functions\n\n### Definition\nA pure function:\n- Always returns the same output for the same input\n- Has no side effects (no I\u002FO, no mutation)\n\n### Examples\n\n```typescript\n\u002F\u002F Pure: Deterministic, no side effects\nconst add = (a: number, b: number): number => a + b;\n\nconst calculateTotal = (items: OrderItem[]): number =>\n  items.reduce((sum, item) => sum + item.price * item.quantity, 0);\n\nconst filterActiveUsers = (users: User[]): User[] =>\n  users.filter((user) => user.isActive);\n\n\u002F\u002F Impure: Has side effects\nconst saveUser = async (user: User): Promise\u003Cvoid> => {\n  await database.save(user); \u002F\u002F I\u002FO side effect\n};\n\nconst logMessage = (msg: string): void => {\n  console.log(msg); \u002F\u002F Side effect\n};\n\nconst generateId = (): string => {\n  return crypto.randomUUID(); \u002F\u002F Non-deterministic\n};\n```\n\n### Pure Core, Impure Shell\n\n```typescript\n\u002F\u002F Pure core - all business logic\nconst validateOrder = (order: Order): Result\u003COrder, ValidationError> => {\n  if (!order.items.length) return Result.fail({ code: 'EMPTY_ORDER' });\n  if (order.total \u003C 0) return Result.fail({ code: 'INVALID_TOTAL' });\n  return Result.ok(order);\n};\n\nconst calculateDiscount = (order: Order, user: User): number => {\n  const baseDiscount = user.isPremium ? 0.15 : 0;\n  const volumeDiscount = order.items.length > 10 ? 0.05 : 0;\n  return baseDiscount + volumeDiscount;\n};\n\nconst applyDiscount = (order: Order, discountRate: number): Order => ({\n  ...order,\n  total: order.total * (1 - discountRate),\n});\n\n\u002F\u002F Impure shell - handles I\u002FO\nconst processOrderHandler = (deps: Dependencies) => async (order: Order) => {\n  const validation = validateOrder(order);\n  if (validation.isFailure) return validation;\n\n  const user = await deps.userRepo.findById(order.userId); \u002F\u002F I\u002FO\n  const discount = calculateDiscount(validation.value, user);\n  const discounted = applyDiscount(validation.value, discount);\n\n  await deps.orderRepo.save(discounted); \u002F\u002F I\u002FO\n  await deps.notifier.send(user.email, 'Order confirmed'); \u002F\u002F I\u002FO\n\n  return Result.ok(discounted);\n};\n```\n\n## Immutability\n\n### Immutable Updates\n\n```typescript\n\u002F\u002F Bad: Mutation\nconst addItemToCart = (cart: Cart, item: Item) => {\n  cart.items.push(item);\n  cart.total += item.price;\n  return cart;\n};\n\n\u002F\u002F Good: Immutable update\nconst addItemToCart = (cart: Cart, item: Item): Cart => ({\n  ...cart,\n  items: [...cart.items, item],\n  total: cart.total + item.price,\n});\n\n\u002F\u002F Good: Nested immutable update\nconst updateUserAddress = (user: User, address: Partial\u003CAddress>): User => ({\n  ...user,\n  address: {\n    ...user.address,\n    ...address,\n  },\n});\n\n\u002F\u002F Good: Using readonly types\ntype ReadonlyUser = {\n  readonly id: string;\n  readonly email: string;\n  readonly addresses: readonly Address[];\n};\n\n\u002F\u002F Good: Immutable array operations\nconst addItem = \u003CT>(arr: readonly T[], item: T): readonly T[] => [...arr, item];\nconst removeAt = \u003CT>(arr: readonly T[], index: number): readonly T[] =>\n  arr.filter((_, i) => i !== index);\nconst updateAt = \u003CT>(arr: readonly T[], index: number, item: T): readonly T[] =>\n  arr.map((existing, i) => (i === index ? item : existing));\n```\n\n## Function Composition\n\n### Pipe and Compose\n\n```typescript\n\u002F\u002F Pipe: left to right\ntype Fn\u003CA, B> = (a: A) => B;\n\nconst pipe = \u003CA, B, C>(\n  f: Fn\u003CA, B>,\n  g: Fn\u003CB, C>\n): Fn\u003CA, C> => (a) => g(f(a));\n\nconst pipe3 = \u003CA, B, C, D>(\n  f: Fn\u003CA, B>,\n  g: Fn\u003CB, C>,\n  h: Fn\u003CC, D>\n): Fn\u003CA, D> => (a) => h(g(f(a)));\n\n\u002F\u002F Usage\nconst processInput = pipe3(\n  trim,\n  toLowerCase,\n  validateEmail\n);\n\n\u002F\u002F Variadic pipe\nconst pipeAll = \u003CT>(...fns: Array\u003C(x: T) => T>) =>\n  (initial: T): T => fns.reduce((acc, fn) => fn(acc), initial);\n\nconst processString = pipeAll(\n  (s: string) => s.trim(),\n  (s: string) => s.toLowerCase(),\n  (s: string) => s.replace(\u002F\\s+\u002Fg, '-')\n);\n```\n\n### Higher-Order Functions\n\n```typescript\n\u002F\u002F Function that returns a function\nconst withLogging = \u003CT extends (...args: any[]) => any>(fn: T) =>\n  (...args: Parameters\u003CT>): ReturnType\u003CT> => {\n    console.log('Calling with:', args);\n    const result = fn(...args);\n    console.log('Result:', result);\n    return result;\n  };\n\n\u002F\u002F Function that takes a function\nconst retry = \u003CT>(\n  fn: () => Promise\u003CT>,\n  attempts: number = 3\n): Promise\u003CT> =>\n  fn().catch((error) =>\n    attempts > 1 ? retry(fn, attempts - 1) : Promise.reject(error)\n  );\n\n\u002F\u002F Currying\nconst multiply = (a: number) => (b: number): number => a * b;\nconst double = multiply(2);\nconst triple = multiply(3);\n\n\u002F\u002F Partial application\nconst createLogger = (prefix: string) =>\n  (message: string): void => console.log(`[${prefix}] ${message}`);\n\nconst infoLog = createLogger('INFO');\nconst errorLog = createLogger('ERROR');\n```\n\n## Result Pattern (Monadic Error Handling)\n\n### Basic Result Type\n\n```typescript\ntype Result\u003CT, E> =\n  | { readonly _tag: 'Ok'; readonly value: T }\n  | { readonly _tag: 'Err'; readonly error: E };\n\nconst ok = \u003CT>(value: T): Result\u003CT, never> => ({ _tag: 'Ok', value });\nconst err = \u003CE>(error: E): Result\u003Cnever, E> => ({ _tag: 'Err', error });\n\nconst isOk = \u003CT, E>(result: Result\u003CT, E>): result is { _tag: 'Ok'; value: T } =>\n  result._tag === 'Ok';\n\nconst isErr = \u003CT, E>(result: Result\u003CT, E>): result is { _tag: 'Err'; error: E } =>\n  result._tag === 'Err';\n```\n\n### Result Operations\n\n```typescript\n\u002F\u002F Map: transform success value\nconst map = \u003CT, U, E>(\n  result: Result\u003CT, E>,\n  fn: (value: T) => U\n): Result\u003CU, E> =>\n  isOk(result) ? ok(fn(result.value)) : result;\n\n\u002F\u002F MapError: transform error value\nconst mapError = \u003CT, E, F>(\n  result: Result\u003CT, E>,\n  fn: (error: E) => F\n): Result\u003CT, F> =>\n  isErr(result) ? err(fn(result.error)) : result;\n\n\u002F\u002F FlatMap (chain): compose Result-returning functions\nconst flatMap = \u003CT, U, E>(\n  result: Result\u003CT, E>,\n  fn: (value: T) => Result\u003CU, E>\n): Result\u003CU, E> =>\n  isOk(result) ? fn(result.value) : result;\n\n\u002F\u002F Match: exhaustive handling\nconst match = \u003CT, E, R>(\n  result: Result\u003CT, E>,\n  handlers: { ok: (value: T) => R; err: (error: E) => R }\n): R =>\n  isOk(result) ? handlers.ok(result.value) : handlers.err(result.error);\n```\n\n### Chaining Results\n\n```typescript\ntype ValidationError = { field: string; message: string };\ntype ProcessingError = { code: string; details: string };\ntype AppError = ValidationError | ProcessingError;\n\nconst validateInput = (input: unknown): Result\u003CValidInput, ValidationError> => {\n  \u002F\u002F ...\n};\n\nconst processData = (input: ValidInput): Result\u003CProcessedData, ProcessingError> => {\n  \u002F\u002F ...\n};\n\nconst formatOutput = (data: ProcessedData): Output => {\n  \u002F\u002F ...\n};\n\n\u002F\u002F Compose the pipeline\nconst handleRequest = (input: unknown): Result\u003COutput, AppError> => {\n  const validated = validateInput(input);\n  if (isErr(validated)) return validated;\n\n  const processed = processData(validated.value);\n  if (isErr(processed)) return processed;\n\n  return ok(formatOutput(processed.value));\n};\n\n\u002F\u002F Or with flatMap\nconst handleRequestFunctional = (input: unknown): Result\u003COutput, AppError> =>\n  flatMap(validateInput(input), (valid) =>\n    map(processData(valid), formatOutput)\n  );\n```\n\n## Option\u002FMaybe Pattern\n\n```typescript\ntype Option\u003CT> =\n  | { readonly _tag: 'Some'; readonly value: T }\n  | { readonly _tag: 'None' };\n\nconst some = \u003CT>(value: T): Option\u003CT> => ({ _tag: 'Some', value });\nconst none: Option\u003Cnever> = { _tag: 'None' };\n\nconst isSome = \u003CT>(opt: Option\u003CT>): opt is { _tag: 'Some'; value: T } =>\n  opt._tag === 'Some';\n\nconst isNone = \u003CT>(opt: Option\u003CT>): opt is { _tag: 'None' } =>\n  opt._tag === 'None';\n\n\u002F\u002F Operations\nconst mapOption = \u003CT, U>(opt: Option\u003CT>, fn: (value: T) => U): Option\u003CU> =>\n  isSome(opt) ? some(fn(opt.value)) : none;\n\nconst getOrElse = \u003CT>(opt: Option\u003CT>, defaultValue: T): T =>\n  isSome(opt) ? opt.value : defaultValue;\n\nconst fromNullable = \u003CT>(value: T | null | undefined): Option\u003CT> =>\n  value != null ? some(value) : none;\n\n\u002F\u002F Usage\nconst findUser = (id: string): Option\u003CUser> => {\n  const user = users.find((u) => u.id === id);\n  return fromNullable(user);\n};\n\nconst getUserEmail = (id: string): string =>\n  getOrElse(\n    mapOption(findUser(id), (user) => user.email),\n    'unknown@example.com'\n  );\n```\n\n## Dependency Injection via Functions\n\n```typescript\n\u002F\u002F Define dependencies as a type\ntype Dependencies = {\n  userRepo: UserRepository;\n  orderRepo: OrderRepository;\n  logger: Logger;\n  clock: () => Date; \u002F\u002F Even time can be injected\n};\n\n\u002F\u002F Create service factory\nconst createOrderService = (deps: Dependencies) => ({\n  createOrder: async (data: CreateOrderData): Promise\u003CResult\u003COrder, OrderError>> => {\n    const user = await deps.userRepo.findById(data.userId);\n    if (!user) {\n      return err({ code: 'USER_NOT_FOUND', userId: data.userId });\n    }\n\n    const order: Order = {\n      id: generateId(),\n      ...data,\n      createdAt: deps.clock(),\n      status: 'pending',\n    };\n\n    deps.logger.info({ orderId: order.id }, 'Creating order');\n    await deps.orderRepo.save(order);\n\n    return ok(order);\n  },\n});\n\n\u002F\u002F Test with fake dependencies\ndescribe('OrderService', () => {\n  it('should create order', async () => {\n    const deps: Dependencies = {\n      userRepo: { findById: jest.fn().mockResolvedValue({ id: '1' }) },\n      orderRepo: { save: jest.fn() },\n      logger: { info: jest.fn() },\n      clock: () => new Date('2024-01-01'),\n    };\n\n    const service = createOrderService(deps);\n    const result = await service.createOrder({ userId: '1', items: [] });\n\n    expect(isOk(result)).toBe(true);\n  });\n});\n```\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Ffunctional-patterns",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":47,"prompt":57,"zipAvailable":58},[48,51,54],{"tool":49,"command":50},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill functional-patterns",{"tool":52,"command":53},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill functional-patterns",{"tool":55,"command":56},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill functional-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Ffunctional-patterns\u002FSKILL.md",true,[60],{"path":61,"resourceType":62,"resourceTypeDesc":63,"sizeBytes":64,"sourceHtmlUrl":65},"skill-report.json","REFERENCE","参考文档",11546,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fdoubleslashse\u002Ffunctional-patterns\u002Fskill-report.json",[67,81,91,100,106,113],{"skillNo":68,"name":69,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":70,"categories":71,"keywords":77,"publishedAt":32},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[72],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[78,79,80],"model","model hierarchy","model hierarchy skill",{"skillNo":82,"name":83,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":84,"categories":85,"keywords":87,"publishedAt":32},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[86],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},[88,89,90],"MCP","zoom","zoom mcp",{"skillNo":92,"name":93,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":32},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[97,98,99,89],"sdk","zoom apps sdk","apps",{"skillNo":101,"name":102,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":103,"categories":104,"keywords":105,"publishedAt":32},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[102],{"skillNo":107,"name":108,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":109,"categories":110,"keywords":112,"publishedAt":32},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[111],{"categoryNo":73,"categoryName":74,"taxonomyType":75,"taxonomyTypeDesc":76},[108],{"skillNo":114,"name":115,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":116,"categories":117,"keywords":118,"publishedAt":32},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[115]]