import assert from "node:assert"; import { getDefaultTypeParser } from "../lib/parser/type_parser.js"; import { IncompatibleTypesError, subsitutionsEqual, unify } from "../lib/generics/unify.js"; const assertSubsitutionsEqual = (m1,m2) => { if (!subsitutionsEqual(m1,m2)) { throw new Error(`substitutions differ:\n m1 = ${prettySS(m1)}\n m2 = ${prettySS(m2)}`); } }; const mkType = getDefaultTypeParser(); assertSubsitutionsEqual( unify( mkType("Int"), mkType("Int"), ), new Map(), ); assert.throws( () => { unify( mkType("Int"), mkType("Bool") ); }, IncompatibleTypesError, ); assertSubsitutionsEqual( unify( mkType("a -> Int"), mkType("b -> b"), ), new Map([ [mkType("a").symbol, mkType("Int")], [mkType("b").symbol, mkType("Int")], ]), ); assertSubsitutionsEqual( unify( mkType("(a -> Int)"), mkType("[Bool] -> Int"), ), new Map([ [mkType("a").symbol, mkType("[Bool]")], ]), ); assertSubsitutionsEqual( unify( mkType("(a -> a) -> b"), mkType("(Bool -> Bool) -> c"), ), new Map([ [mkType("a").symbol, mkType("Bool")], [mkType("c").symbol, mkType("b")], ]), ); assert.throws( () => { unify( mkType("a -> (a -> Ordering)"), mkType("[b] -> b"), ); }, IncompatibleTypesError, ); assertSubsitutionsEqual( unify( mkType("[a] -> (Int -> a)"), mkType("b -> c"), ), new Map([ [mkType("b").symbol, mkType("[a]")], [mkType("c").symbol, mkType("Int -> a")], ]), ); assert.throws( () => { unify( mkType("[a] -> (Int -> a)"), mkType("b -> (c -> b)"), ); }, IncompatibleTypesError, // String, ); assertSubsitutionsEqual( unify( mkType("a -> b -> a -> b"), mkType("c -> c -> d -> e"), ), new Map([ [mkType("b").symbol, mkType("a")], [mkType("c").symbol, mkType("a")], [mkType("d").symbol, mkType("a")], [mkType("e").symbol, mkType("a")], ]), );