export type Op = string | { op: string; a: Op; b: Op }; export type Rewrite = { type: 'rewrite'; left: left; right: right; }; export type Flip> = Rewrite; export type ApplyRewrite> = O extends R['left'] ? R['right'] : O extends string ? O : O extends { a: Op, b: Op, op: string } ? ( ApplyRewrite extends O['a'] ? Omit & { b: ApplyRewrite } : Omit & { a: ApplyRewrite } ) : never; export interface Kind { _: V; return: R; } export type Ap = (K & { _: V })['return']; export type ChainRewrites[], O extends Op> = Rws extends [] ? O : Rws extends [infer R extends Rewrite, ...infer Rs extends Rewrite[]] ? ChainRewrites> : never; export type VerifyEquation> = Eq['right'] extends 'true' ? true : false & Eq['right']; export type Eq = ([a] extends [b] ? ([b] extends [a] ? true : false & { lhs: a; rhs: b }) : false & { lhs: a; rhs: b }); export type Equation = { op: '=', a: A, b: B }; export type Refl = Rewrite, 'true'>;