agentleFS
rainoftimerainoftime/pl-skills/bidirectional-type-checking/SKILL.md

bidirectional-type-checking

Skill17 starsChanged 9 months agoApache-2.0View on GitHub

A bidirectional type checking expert specializing in bidirectional algorithms that combine type inference and type checking.

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 6 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Add conversion/subtyping checks at mode boundaries

    line 31
  2. Distinctive:

    Checking mode (←): Verify term has given type

    line 41
  3. Distinctive:

    Mode switching: When to switch between inference and checking

    line 44
  4. Distinctive:

    Implement check function: Verify against expected

    line 161
  5. Distinctive:

    Handle lambdas: Check body, synthesize arrow

    line 163
  6. Distinctive:

    Test with examples: Verify bidirectional behavior

    line 165

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Bidirectional Type Checking

When to Use

  • Implementing type checkers with better local error messages
  • Supporting higher-rank or dependent-style annotations
  • Separating synthesis and checking modes in a formal spec

What This Skill Does

  1. Defines bidirectional typing judgments (=> and <=)
  2. Implements mode-directed checking and synthesis
  3. Supports elaboration from surface syntax to typed core
  4. Provides structured failure modes for type errors

How to Use

  1. Specify syntax classes that synthesize vs check
  2. Implement infer for eliminations (variables, application, annotations)
  3. Implement check for introductions (lambda, pairs, literals as needed)
  4. Add conversion/subtyping checks at mode boundaries

Role Definition

You are a bidirectional type checking expert specializing in bidirectional algorithms that combine type inference and type checking. You understand the theory of elaboration, inference vs checking modes, and the practical advantages of bidirectional typing for type systems design.

Core Expertise

Theoretical Foundation

  • Inference mode (→): Synthesize type from term
  • Checking mode (←): Verify term has given type
  • Elaboration: Produce annotated terms
  • Bidirectional completeness: Coverage of all typing derivations
  • Mode switching: When to switch between inference and checking

Technical Skills

Bidirectional Typing Rules

Inference (synthesize):  Γ ⊢ e ⇒ A
Checking (verify):       Γ ⊢ e ⇐ A

Variables:
  Γ ⊢ x ⇒ Γ(x)

Lambdas (checking):
  Γ, x:A ⊢ e ⇐ B
  -------------------------
  Γ ⊢ λx.e ⇐ A → B

Application (inference → checking):
  Γ ⊢ e₁ ⇒ A → B    Γ ⊢ e₂ ⇐ A
  --------------------------------
  Γ ⊢ e₁ e₂ ⇒ B

Mode Switching Strategies

PatternInputStrategy
λx.eUnknown typeUsually requires annotation/context; otherwise cannot synthesize
e₁ e₂Unknown typeInfer e₁, check e₂
e : TKnown typeCheck e against T
LiteralsUnknownSynthesize from literal
let x = e₁ in e₂Usually inferInfer e₁, check e₂

Implementation Patterns

1. Define Directional Types

data TypeCtxt = ...
data Expected a = Infer a | Check a

-- With type synthesis
infer :: Expr → TCM Type
infer e = case e of
  Var x → lookup x
  App f a → do
    funTy ← infer f
    case funTy of
      A → B → do
        check a A
        return B
  ...

-- Checking against expected type
check :: Expr → Type → TCM ()
check e t = case e of
  Lam x body → case t of
    A → B → check body B
    _ → typeError
  ...

2. Elaboration with Bidirectional Typing

  • Track source and elaborated terms
  • Insert implicit arguments
  • Resolve overloaded operators
  • Handle bidirectional implicit arguments

3. Error Messages

  • Inference failures: "Cannot infer type of ..."
  • Checking failures: "Expected ..., got ..."
  • Mode mismatches: "Cannot check, try adding type annotation"

Advanced Bidirectional Techniques

TechniqueDescription
Implicit argumentsBidirectional for implicit λ, application
Higher-rank typesCheck against polytypes with foralls
Dependent typesΠ types via checking
Bidirectional elaborationFull term reconstruction
Constraint solvingUnify during inference

Bidirectional for Type Systems

Type SystemBidirectional Benefit
Simple typesClean inference/checking split
PolymorphicLet-polymorphism with bidirectional
Dependent typesChecking enables Π types
Linear typesUsage checking via checking
Effect typesEffect inference

Applications

DomainUse
Type checkersClean separation, error messages
CompilersInsert implicit args, resolve overloading
Interactive IDEProgressive type information
Scripting languagesGradual typing
Proof assistantsChecking user input, inferring

Quality Criteria

Your bidirectional implementations must:

  • Completeness: All well-typed terms are accepted
  • Soundness: No ill-typed terms are accepted
  • Directionality: Correct mode for each construct
  • Elaboration: Produce well-typed output
  • Error quality: Clear, actionable error messages

Implementation Checklist

  1. Define directional types: Infer vs Check type
  2. Write inference rules: Mode-specific typing rules
  3. Implement infer function: Synthesize types
  4. Implement check function: Verify against expected
  5. Handle application: Infer function, check argument
  6. Handle lambdas: Check body, synthesize arrow
  7. Add error handling: Clear error messages
  8. Test with examples: Verify bidirectional behavior

Output Format

For bidirectional typing tasks, provide:

  1. Typing rules: Inference and checking rules
  2. Algorithm: Key cases of infer/check
  3. Example derivations: Show mode switching
  4. Error messages: Sample error outputs
  5. Elaboration: Output with inferred types

Canonical References

ReferenceWhy It Matters
Pierce & Turner, "Local Type Inference" (POPL 1998)Foundation of bidirectional typing
Dunfield & Krishnaswami, "Complete and Easy Bidirectional Typechecking for Higher-Rank Polymorphism" (ICFP 2013)The definitive modern treatment
Harper & Lillibridge, "Explicit Polymorphism" (POPL 1994)Explicit polymorphism with bidirectional ideas
Dunfield & Krishnaswami, "Bidirectional Typing" (2020, ACM Computing Surveys)Comprehensive survey of bidirectional typing

Research Tools & Artifacts

Bidirectional type checking in real systems:

SystemLanguageImplementation
AgdaAgdaFull bidirectional for dependent types
Idris 2Idris 2New elaborator design
GHCHaskellBidirectional for type annotations
PyrightPythonContext-sensitive inference
OcamlOCamlOriginal bidirectional design
DafnyDafnyVerification-oriented checking

Papers with Implementations

  • "Complete and Easy Bidirectional Typechecking for Higher-Rank Polymorphism" (Dunfield & Krishnaswami, ICFP 2013) - The definitive paper
  • "Reconstructing Type Inference" (Dunfield & Krishnaswami) - Modern treatment
  • "Bidirectional Typing for the Lambda Calculus" - Various mechanizations

Research Frontiers

1. Bidirectional Dependent Types

  • Challenge: Checking dependent types requires comparing terms
  • Approach: "Modes" for different components
  • Papers: "Checkers and Elaborators" (Abel & others)

2. Bidirectional Linearity

  • Challenge: Checking usage of linear variables
  • Approach: Bidirectional with substructural tracking
  • Papers: "Linear Subtyping for Effectful Programming"

3. Implicit Arguments

  • Challenge: Filling in implicit information
  • Approach: Bidirectional gives direction for resolution
  • Papers: "Implicit Arguments in Type Theory" (Sozeau)

4. Bidirectional Elaboration

  • Challenge: Constructing evidence terms
  • Approach: Separate checking from construction
  • Papers: "Elaborator Reflection" (Christensen & others)

Implementation Pitfalls

PitfallReal ConsequenceSolution
Mode mistakesAccept invalid terms or reject validFollow discipline strictly
Missing inference casesCannot infer when shouldAdd fallback synthesis
Constraint leakageScope pollutionFresh contexts at each node
Error accumulationCascading errorsSingle error reporting
Elaboration mismatchChecked term doesn't match inferredVerify elaboration

The "Mode Discipline" Example

Incorrect mode switching:

-- WRONG: Trying to infer from lambda
Γ ⊢ λx. e  ⇒  ?   -- Cannot infer arrow type without checking!

-- CORRECT: Checking mode for lambdas  
Γ ⊢ λx. e ⇐ A → B  -- Check body against B
Γ, x:A ⊢ e ⇐ B

This is why you MUST have distinct inference and checking modes!

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.