agentleFS
rainoftimerainoftime/pl-skills/effect-type-system/SKILL.md

effect-type-system

Skill17 starsChanged 9 months agoApache-2.0View on GitHub

Implements algebraic effect types. Use when: (1) Handling side effects,

The file

We split this skill into the rules it gives an agent

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

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    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:

    Use handlers for I/O

    line 254
  2. Distinctive:

    For teaching: Start with monads

    line 286

≈ “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

Effect Type System

Implements algebraic effect type system for tracking computations.

When to Use

  • Effect inference
  • Handler design
  • Extensible effects
  • Effect polymorphism

What This Skill Does

  1. Defines effects - Algebraic effect signatures
  2. Tracks operations - Effectful computations
  3. Handles effects - Effect handlers
  4. Infers effects - Effect inference

Core Theory

Effect Signature:
  effect State: get : Unit → Int
              put : Int → Unit
  
Effect Type:
  Computation with effect set
  T => E   (T with effects E)
  
Handler:
  handle expr with
    return x => x
  | get(k) => ...

Implementation

from dataclasses import dataclass, field
from typing import Dict, List, Set, Optional

@dataclass
class EffectOp:
    """Effect operation"""
    effect: str
    name: str
    param_type: 'Type'
    return_type: 'Type'

@dataclass
class EffectSet:
    """Set of effects"""
    effects: Set[str] = field(default_factory=set)
    
    def union(self, other: 'EffectSet') -> 'EffectSet':
        return EffectSet(self.effects | other.effects)
    
    def empty(self) -> bool:
        return len(self.effects) == 0

@dataclass
class EffectType:
    """Type with effects"""
    result: 'Type'
    effects: EffectSet

@dataclass
class Type:
    """Base type"""
    pass

@dataclass
class TInt(Type):
    pass

@dataclass
class TString(Type):
    pass

@dataclass  
class TFun(Type):
    param: Type
    result: EffectType  # Function has effect type

class EffectChecker:
    """Check effect typing"""
    
    def __init__(self):
        self.effect_sigs: Dict[str, Dict[str, EffectOp]] = {}
        self.handlers: Dict[str, EffectType] = {}
    
    def declare_effect(self, name: str, ops: Dict[str, EffectOp]):
        """Declare effect signature"""
        self.effect_sigs[name] = ops
    
    def check(self, expr: 'Expr', env: Dict) -> EffectType:
        """Check expression effect type"""
        
        match expr:
            case Const(n):
                return EffectType(TInt(), EffectSet())
            
            case Var(x):
                return env[x]
            
            case Lambda(x, body):
                body_type = self.check(body, {**env, x: EffectType(TInt(), EffectSet())})
                return EffectType(
                    TFun(TInt(), body_type),
                    body_type.effects
                )
            
            case App(func, arg):
                func_type = self.check(func, env)
                arg_type = self.check(arg, env)
                
                if isinstance(func_type.result, TFun):
                    # Check effect handling
                    return func_type.result.result
                raise TypeError("Not a function")
            
            case Perform(effect, op, arg):
                # Perform effect operation
                if effect in self.effect_sigs:
                    op_sig = self.effect_sigs[effect].get(op)
                    if op_sig:
                        return EffectType(
                            op_sig.return_type,
                            EffectSet({effect})
                        )
                raise TypeError(f"Unknown effect operation: {effect}.{op}")
            
            case Handle(body, handler):
                # Handle effects in body
                body_type = self.check(body, env)
                
                # Check handler covers effects
                uncovered = body_type.effects.effects - set(handler.effects.keys())
                if uncovered:
                    raise TypeError(f"Unhandled effects: {uncovered}")
                
                # Handler produces pure result
                return EffectType(handler.return_type, EffectSet())
    
    def infer(self, expr: 'Expr', env: Dict) -> EffectType:
        """Infer effect type"""
        
        # Similar to check but with inference
        return self.check(expr, env)

# Example: State effect
def state_effect_example():
    """
    effect State:
      get : () -> Int
      put : Int -> ()
    
    let counter =
      handle
        let x = perform State.get() in
        perform State.put(x + 1);
        x
      with
        return x -> x
      | get(k) -> k(0)  -- handler provides state
      | put(n) -> k(())  -- handler continues
    
    Type: () => {State}
    """
    pass

Effect Handlers

@dataclass
class Handler:
    """Effect handler"""
    effect: str
    return_clause: 'Clause'  # return x => expr
    ops: Dict[str, 'Clause']  # op(k) => expr

class HandlerTypechecker:
    """Typecheck handlers"""
    
    def check_handler(self, handler: Handler, eff_type: EffectType) -> Type:
        """Check handler type"""
        
        # Check return clause type matches
        # Check each operation handler type
        for op_name, clause in handler.ops.items():
            # op(k) => body
            # k: T -> U where T is op param type
            # body must produce U
            pass
        
        return handler.return_clause.result_type

Key Concepts

ConceptDescription
EffectObservable computation
HandlerHandle effect operations
OperationEffect primitive
ResumeContinue computation

Effect Inference

class EffectInference:
    """Infer effects"""
    
    def infer_effects(self, expr: 'Expr') -> EffectSet:
        """Infer effect set"""
        
        # Collect effects
        effects = set()
        
        def visit(e):
            if isinstance(e, Perform):
                effects.add(e.effect)
            for child in e.children:
                visit(child)
        
        visit(expr)
        return EffectSet(effects)

Tips

  • Declare effect signatures
  • Handle all effects
  • Consider polymorphism
  • Use handlers for I/O

Related Skills

  • type-inference-engine - Type inference
  • linear-type-implementer - Linear types
  • effect-type-system - Effects

Canonical References

ReferenceWhy It Matters
Plotkin & Pretnar, "Handlers of Algebraic Effects" (ESOP 2009)Foundational paper on effect handlers
Bauer & Pretnar, "Programming with Algebraic Effects and Handlers" (J. LAMP, 2015)Effect handlers tutorial and the Eff language
Kammar, Lindley, Oury, "Handlers in Action" (ICFP 2013)Popularized handlers with implementations
Plotkin & Power, "Notions of Computation Determine Monads" (2002)Algebraic foundations of effects
Leijen, "Koka: Programming with Row Polymorphic Effect Types" (MSFP 2014)Practical effect-typed language

Tradeoffs and Limitations

Effect System Tradeoffs

ApproachProsCons
Row polymorphismFlexibleComplex inference
Effect subscriptionsExplicitVerbose
Implicit effectsConvenientHard to track

When NOT to Use Effect Types

  • For simple programs: Monads may be simpler
  • For IO-heavy code: Direct IO may be clearer
  • For teaching: Start with monads

Complexity Considerations

  • Effect inference: Can be complex
  • Handler composition: Non-trivial
  • Polymorphism: Requires care

Limitations

  • Inference difficulty: Effect inference hard
  • Handler complexity: Multiple handlers complex
  • Error messages: Hard to make clear
  • Performance: Handler overhead
  • Interaction with exceptions: Complex
  • Debugging: Hard to trace effects
  • Tooling: IDE support limited

Research Tools & Artifacts

Real-world effect type systems:

ToolWhy It Matters
KokaProduction effect-typed language
FrankEffect handlers with inference
EffEffect language research
Multicore OCamlExperimental effects
HaskellMonad transformers for effects

Famous Effect Systems

  • Koka: Microsoft effect language
  • Frank:(handler f) -> T syntax

Research Frontiers

Current effect system research:

DirectionKey PapersChallenge
Effect rows"Row Polymorphism"Extensible effects
Effect handlers"Handlers of Algebraic Effects"Handler composition
Effect inference"Inference for Effects"Automating inference

Hot Topics

  1. Effects in Rust: Effects RFC
  2. Effects in Python: PEP proposal

Implementation Pitfalls

Common effect system bugs:

PitfallReal ExamplePrevention
Effect explosionToo many effects inferredPolymorphism
Wrong handlerWrong effect handledHandler ordering
SubeffectingWrong subeffect relationCheckrows

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.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

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.