Skip to content

Instantly share code, notes, and snippets.

@ninjudd
Last active April 14, 2026 19:14
Show Gist options
  • Select an option

  • Save ninjudd/a6936ce00b6cfc37d5a75a958435c3aa to your computer and use it in GitHub Desktop.

Select an option

Save ninjudd/a6936ce00b6cfc37d5a75a958435c3aa to your computer and use it in GitHub Desktop.
Functor example
const selectTopic = functor({
prompt: ({ query, topics }: { query: string; topics: string }) => `
User query: ${query}
Existing topics:
${topics}
Match an existing topic if one fits, otherwise create a new one.
`,
returns: [
{
type: 'choose_existing',
description: 'Pick an existing topic that matches',
schema: z.object({ topicId: z.string() }),
},
{
type: 'create_new',
description: 'Create a new topic when none match',
schema: z.object({
name: z.string(),
summary: z.string(),
}),
},
],
});
const extractPatient = functor({
prompt: ({ text }: { text: string }) => `
Extract patient info from the text below.
Return whatever fields are present.
${text}
`,
returns: {
description: 'Extract basic patient demographics if present',
schema: z.object({
name: z.string().optional(),
birthDate: z.string().optional(),
gender: z.string().optional(),
}),
},
});
const patient = await extractPatient({ text: documentText });
@ninjudd

ninjudd commented Apr 14, 2026

Copy link
Copy Markdown
Author

A small shift that’s changed how we build at Triangle: treat LLMs as functions, not chatbots or agents.

One call. Typed input. Typed output. No conversation, no loop.

We call them Functors.

@ninjudd

ninjudd commented Apr 14, 2026

Copy link
Copy Markdown
Author

The schema is the return type. The prompt is the implementation.

What followed was realizing how much of a codebase can be written this way.

A lot of regexes and hand-rolled parsers were just deterministic answers to non-deterministic questions.

@ninjudd

ninjudd commented Apr 14, 2026

Copy link
Copy Markdown
Author

Prompts are just another programming language now.

You write functions in prose, then compose them with the rest of your code like anything else: called from a worker, an API route, or a UI handler.

Functors have a stable interface. They behave like any code: testable, versioned.

@ninjudd

ninjudd commented Apr 14, 2026

Copy link
Copy Markdown
Author

Need more than one return shape? The prompt stays a typed function, returns becomes an array, and you get a typed discriminated union. Dispatched in prose.

The trick that makes it work: tool calling, used to select and enforce return types.

Each return is a schema plus a short description.

The model thinks it’s choosing an action. We use it to select the shape of the return value.

@ninjudd

ninjudd commented Apr 14, 2026

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment