// Given, not an exercise: the course's data types, written down for an editor that understands types (optional, // see Module 0, "If your editor understands types"). Nothing imports this file at run time; the JS files refer to it // from their doc comments (`@import`, `@type`). Every sum type is a union of plain objects with a `tag`, so a // `switch (x.tag)` narrows `x` to one case inside each `case`. // ---- m02 model, m10 replay viewer, m11 Pong, m13 Life // The model types are written where the model is: as `@typedef` comments in model.js (Module 2 shows them there), // pong/model.js, life/model.js and replay.js. Each action union sits next to the object of the same name that // builds its values, so `import { Action } from './model.js'` gives both. They are re-exported here so that every // type can be found in one place. import type { Point, Direction, Status, Action, GameState } from './model.js' import type { Viewer, ViewerAction } from './replay.js' import type { PongState, PongAction } from './pong/model.js' import type { LifeState, LifeAction } from './life/model.js' export type { Point, Direction, Status, Action, GameState, Viewer, ViewerAction, PongState, PongAction, LifeState, LifeAction } // ---- m04 random and state /** A random value: a function from a seed to the value and the next seed. */ export type Random = (seed: number) => [A, number] /** A value that reads and replaces a state of type S. `Random` is `State`. */ export type State = (s: S) => [A, S] // ---- m06 view export type Align = 'left' | 'center' | 'right' export type Shape = | { tag: 'Rect'; x: number; y: number; w: number; h: number; color: string } | { tag: 'Text'; x: number; y: number; text: string; color: string; size: number; align: Align } export type Scene = Shape[] // ---- m07 IO export type Op = | { tag: 'Draw'; shape: Shape } | { tag: 'RandomSeed' } | { tag: 'LoadBest' } | { tag: 'SaveBest'; score: number } /** A program that produces an A. The answer given to `k` depends on the op (a number, or undefined), hence `any`. */ export type IO = | { tag: 'Pure'; value: A } | { tag: 'Effect'; op: Op; k: (answer: any) => IO } /** What the pure interpreters return: the program's result and the ops it performed, in order. */ export type Trace = { result: A; ops: Op[] } // ---- m07b stack-safe IO export type SafeIO = | { tag: 'Pure'; value: A } | { tag: 'Effect'; op: Op; k: (answer: any) => SafeIO } | { tag: 'FlatMap'; io: SafeIO; f: (result: any) => SafeIO } // ---- m08 streams /** What the world feeds a stream. `Click` arrives in Module 13. */ export type Input = | { tag: 'Time'; t: number } | { tag: 'KeyDown'; key: string } | { tag: 'KeyUp'; key: string } | { tag: 'Click'; x: number; y: number } export type Stream = { step: (input: Input) => [A[], Stream] } /** The whole program: ask the world for what it needs, then a stream of drawings. */ export type Program = IO>> // ---- m09 runtime export type Platform = { fillRect: (x: number, y: number, w: number, h: number, color: string) => void fillText: (x: number, y: number, text: string, color: string, size: number, align: Align) => void randomSeed: () => number loadBest: () => number saveBest: (score: number) => void startClock: (onTime: (t: number) => void) => void onKeyDown: (cb: (key: string) => void) => void onKeyUp: (cb: (key: string) => void) => void onClick: (cb: (x: number, y: number) => void) => void } // ---- m10 high score and replay viewer export type Session = { game: GameState; best: number; improved: boolean } /** A recorded game (`fixtures/replay-sample.json`). */ export type Recording = { seed: number; actions: Action[] } // ---- m12 property-based testing export type CheckResult = { ok: true; runs: number } | { ok: false; run: number; seed: number; value: A }