
type-checker-tests
by purefunctor
type-checker-testsは、other分野における実用的なスキルです。複雑な課題への対応力を強化し、業務効率と成果の質を改善します。
SKILL.md
name: type-checker-tests description: Add integration tests for type checker inference and checking functions allowed-tools: Bash(mkdir:*)
Type Checker Integration Tests
Use this skill when adding new type checker functions or expanding behavior.
Language: Test fixtures use PureScript syntax, not Haskell.
Quick Reference
| Action | Command |
|---|---|
| Find next test number | ls tests-integration/fixtures/checking/ | tail -5 |
| Run a test or multiple tests | just tc NNN or just tc 101 102 |
| Run with tracing enabled | just tc --debug NNN |
| Run all checking tests | just tc |
| Accept all pending snapshots | cargo insta accept |
Use just tc --help for all options.
Creating a Test
1. Create fixture directory
mkdir tests-integration/fixtures/checking/{NNN_descriptive_name}
Tests are auto-discovered by build.rs - no manual registration needed.
2. Write Main.purs
Standard pattern - pair typed (checking) and untyped (inference) variants:
module Main where
-- Checking mode: explicit signature constrains type checker
test :: Array Int -> Int
test [x] = x
-- Inference mode: type checker infers unconstrained
test' [x] = x
Guidelines:
- Test ONE specific behavior per fixture
- Name tests descriptively:
test,test',test2,test2', etc. - Include edge cases relevant to the behavior being tested
3. Generate and review snapshot
just tc NNN
This outputs:
CREATED path(green) with numbered lines showing full contentUPDATED path(yellow) with chunked diff (2 lines context, line numbers)
Multi-File Tests
For testing imports, re-exports, or cross-module behavior, add multiple .purs files
to the same fixture directory. The type checker loads all .purs files in the folder.
Example structure:
tests-integration/fixtures/checking/NNN_import_test/
├── Main.purs # The test file (snapshot generated for Main)
├── Lib.purs # Supporting module
└── Main.snap # Generated snapshot
Lib.purs:
module Lib where
life :: Int
life = 42
data Maybe a = Just a | Nothing
Main.purs:
module Main where
import Lib (life, Maybe(..))
test :: Maybe Int
test = Just life
Key points:
- Module name must match filename (
Lib.purs->module Lib where) - Only
Main.pursgenerates a snapshot (the test runs againstMain) - Use standard PureScript import syntax
Reviewing Snapshots
Snapshots have this structure:
Terms
functionName :: InferredOrCheckedType
...
Types
TypeName :: Kind
...
Errors
ErrorKind { details } at [location]
Acceptance Criteria
Before accepting, verify:
-
Types are correct - Check that inferred types match expectations
test :: Array Int -> Int- explicit signature preservedtest' :: forall t. Array t -> t- polymorphism inferred correctly
-
No unexpected
???- This indicates inference failuretest :: ???- STOP: the term failed to type checkCannotUnify { ??? -> ???, Int }- OK in error tests, shows unresolved unification variables
-
Errors appear where expected - For tests validating error behavior
- Confirm error kind matches expectations (e.g.,
NoInstanceFound,CannotUnify) - Verify error location points to the correct declaration
- Confirm error kind matches expectations (e.g.,
-
Polymorphism is appropriate
- Check type variable names (
t6,a, etc.) are scoped correctly - Verify constraints propagate as expected
- Check type variable names (
Common Issues
| Symptom | Likely Cause |
|---|---|
test :: ??? | Test code has syntax error or uses undefined names |
| Unexpected monomorphism | Missing polymorphic context or over-constrained signature |
| Wrong error location | Check binder/expression placement in source |
| Missing types in snapshot | Module header or imports incorrect |
Accept and Verify
# Accept only after thorough review
cargo insta accept
# Verify all checking tests pass
just tc
Debugging
When investigating a potential compiler bug:
# Focus on single test to reduce noise
just tc NNN
# Enable tracing to see type checker behaviour
just tc --debug NNN
Trace Files
The --debug flag emits detailed type checker traces to target/compiler-tracing/.
Trace file naming: {test_id}_{module_name}.jsonl
- Example:
200_int_compare_transitive_Main.jsonl
Output format: JSON Lines (one JSON object per line), containing:
timestamp- when the event occurredlevel- DEBUG, INFO, or TRACEfields- trace data (e.g., types being unified)target- the module emitting the trace (e.g.,checking::algorithm::unification)span/spans- current span and span stack
Example trace line:
{"timestamp":"...","level":"DEBUG","fields":{"t1":"?0","t2":"Int"},"target":"checking::algorithm::unification","span":{"name":"unify"}}
When --debug is used, the trace file path is shown alongside pending snapshots:
UPDATED tests-integration/fixtures/checking/200_int_compare_transitive/Main.snap
TRACE target/compiler-tracing/200_int_compare_transitive_Main.jsonl
Analysing Traces
Trace files can be large for complex tests. Use sampling and filtering:
# Check file size and line count
wc -l target/compiler-tracing/NNN_*.jsonl
# Sample random lines to get an overview
shuf -n 20 target/compiler-tracing/NNN_*.jsonl | jq .
# Filter by level
jq 'select(.level == "DEBUG")' target/compiler-tracing/NNN_*.jsonl
# Filter by target module
jq 'select(.target | contains("unification"))' target/compiler-tracing/NNN_*.jsonl
# Extract specific fields
jq '{level, target, fields}' target/compiler-tracing/NNN_*.jsonl
You should run just tc to check for regressions.
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です



