diff options
Diffstat (limited to 'src/scenes')
39 files changed, 1181 insertions, 18 deletions
diff --git a/src/scenes/boolean_algebra_lambda.meta b/src/scenes/boolean_algebra_lambda.meta new file mode 100644 index 0000000..385a68c --- /dev/null +++ b/src/scenes/boolean_algebra_lambda.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2667185663 +}
\ No newline at end of file diff --git a/src/scenes/boolean_algebra_lambda.tsx b/src/scenes/boolean_algebra_lambda.tsx new file mode 100644 index 0000000..2639461 --- /dev/null +++ b/src/scenes/boolean_algebra_lambda.tsx @@ -0,0 +1,49 @@ +import { Layout, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { LambdaReducer } from "../components/lambda_reducer"; +import { baseDefinitions } from "../utils/lambdas"; + +export default makeScene2D(function* (view) { + const lambdaReducer = createRef<LambdaReducer>(); + const layout = createRef<Layout>(); + + view.add( + <Layout + layout + ref={layout} + direction="column" + alignItems="center" + gap={50} + ></Layout> + ); + yield* slideTransition(Direction.Right); + yield* beginSlide("Boolean Reductions"); + + for (const term of [ + "((false one) zero)", + "((true one) zero)", + "(((if true) one) zero)", + ]) { + yield* layout().opacity(0, 0.5); + layout().add( + <LambdaReducer + ref={lambdaReducer} + lambdaTerm={term} + definitions={baseDefinitions} + ></LambdaReducer> + ); + yield* layout().opacity(1, 0.5); + + yield* beginSlide("Next Reduction " + term); + for (let i = 0; !lambdaReducer().isDone(); i++) { + yield* lambdaReducer().step(0.5); + yield* beginSlide(term + " Next Step " + i); + } + layout().removeChildren(); + } +}); diff --git a/src/scenes/boolean_encoding.meta b/src/scenes/boolean_encoding.meta new file mode 100644 index 0000000..8f4d744 --- /dev/null +++ b/src/scenes/boolean_encoding.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2394701117 +}
\ No newline at end of file diff --git a/src/scenes/boolean_encoding.tsx b/src/scenes/boolean_encoding.tsx new file mode 100644 index 0000000..60a0ea9 --- /dev/null +++ b/src/scenes/boolean_encoding.tsx @@ -0,0 +1,42 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const boolE = [ + "true = λ t . λ f . t", + "false = λ t . λ f . f", + "if = λ b . λ x . λ y . b x y", + "not = λ b . b false true", + "and = λ b . λ c . b c false", +]; + +export default makeScene2D(function* (view) { + const numerals = createRef<Txt>(); + + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + Boolean Encoding + </Txt> + <Txt + ref={numerals} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("The Lambda Calculus - Boolean Encoding"); + + for (const bool of boolE) { + yield* numerals().text(numerals().text() + "\n\n" + bool, 1); + yield* beginSlide("boolean - " + bool); + } +}); diff --git a/src/scenes/church_encoding.meta b/src/scenes/church_encoding.meta new file mode 100644 index 0000000..638e825 --- /dev/null +++ b/src/scenes/church_encoding.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 533121975 +}
\ No newline at end of file diff --git a/src/scenes/church_encoding.tsx b/src/scenes/church_encoding.tsx new file mode 100644 index 0000000..70bafe4 --- /dev/null +++ b/src/scenes/church_encoding.tsx @@ -0,0 +1,41 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const churchNumerals = [ + "0 = λ f . λ x . x (no application of f)", + "1 = λ f . λ x . f x (one application of f)", + "2 = λ f . λ x . f (f x) (two applications of f)", + "succ = λ n . λ f . λ x . f ((n f) x)", +]; + +export default makeScene2D(function* (view) { + const numerals = createRef<Txt>(); + + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + Church Encoding + </Txt> + <Txt + ref={numerals} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("The Lambda Calculus - Church Encoding"); + + for (const numeral of churchNumerals) { + yield* numerals().text(numerals().text() + "\n\n" + numeral, 1); + yield* beginSlide("substitution - " + numeral); + } +}); diff --git a/src/scenes/currying.meta b/src/scenes/currying.meta new file mode 100644 index 0000000..1dd71f1 --- /dev/null +++ b/src/scenes/currying.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2262306570 +}
\ No newline at end of file diff --git a/src/scenes/currying.tsx b/src/scenes/currying.tsx new file mode 100644 index 0000000..01ce24a --- /dev/null +++ b/src/scenes/currying.tsx @@ -0,0 +1,114 @@ +import { Video, Layout, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + all, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { PEOPLE, Person, PersonI } from "../components/person"; +import { birthdayCardFn, valentineCardFn } from "./generalized"; +import { CardI } from "./birthday_letters"; +import { FunctionBox } from "../components/function_box"; +import curry from "../../public/img/curry.mp4"; + +export const cardGeneratorsFor = ( + person: PersonI, +): ((type: string) => () => CardI) => { + const birthdayCardGenerator = () => birthdayCardFn(person); + const valentineCardGenerator = () => valentineCardFn(person); + + const messageType = (type: string) => { + switch (type) { + case "valentine": + return valentineCardGenerator; + case "birthday": + return birthdayCardGenerator; + } + throw new Error(type + " not implemented"); + }; + + return messageType; +}; + +export const cardGeneratorsForSource = `const cardGeneratorsFor = (person: PersonI): ((type: string) => () => CardI) => { + const birthdayCardGenerator = () => birthdayCardFn(person); + const valentineCardGenerator = () => valentineCardFn(person); + + const generatorForType = (type: string) => { + switch (type) { + case "valentine": + return valentineCardGenerator; + case "birthday": + return birthdayCardGenerator; + } + + throw new Error(type + " not implemented"); + }; + + return generatorForType; +};`; + +export default makeScene2D(function* (view) { + const box = createRef<FunctionBox>(); + const vid = createRef<Video>(); + + view.add( + <Layout> + <FunctionBox + ref={box} + fn={cardGeneratorsFor} + source={cardGeneratorsForSource} + outputFontSize={20} + /> + <Video ref={vid} src={curry} width={0} /> + </Layout>, + ); + + yield* all( + box().reset(0.1), + box().showCode(0.5), + slideTransition(Direction.Left, 0.5), + ); + + yield* beginSlide("show code"); + + const [alan] = PEOPLE; + yield* box().setInputs([{ val: alan, node: <Person person={alan} /> }], 0.5); + + yield* beginSlide("show inputs"); + + yield* box().hideCode(0.5); + yield* box().propogateInput(0.5); + yield* box().propogateOutput(0.5); + + yield* beginSlide("create child function"); + + const child = box().getChild(); + yield* child().showCode(0.5); + + yield* beginSlide("show child function"); + + yield* child().hideCode(0.5); + yield* child().setInputs([{ val: "valentine" }], 0.5); + yield* child().propogateInput(0.5); + yield* child().propogateOutput(0.5); + + const curriedChild = child().getChild(); + yield* curriedChild().showCode(0.5); + + yield* beginSlide("propogate child function"); + + yield* curriedChild().hideCode(0.5); + yield* curriedChild().setInputs([{ val: "" }], 0.5); + yield* curriedChild().propogateInput(0.5); + yield* curriedChild().propogateOutput(0.5); + + yield* beginSlide("propogate curry"); + + yield vid().play(); + yield vid().loop(true); + yield* vid().width(400, 2); + + yield* beginSlide("do i smell curry"); +}); diff --git a/src/scenes/currying_detail.meta b/src/scenes/currying_detail.meta new file mode 100644 index 0000000..71a034a --- /dev/null +++ b/src/scenes/currying_detail.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2012730104 +}
\ No newline at end of file diff --git a/src/scenes/currying_detail.tsx b/src/scenes/currying_detail.tsx new file mode 100644 index 0000000..fd7c3d3 --- /dev/null +++ b/src/scenes/currying_detail.tsx @@ -0,0 +1,155 @@ +import { Layout, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { + CodeBlock, + edit, + insert, + range, +} from "@motion-canvas/2d/lib/components/CodeBlock"; +import { cardGeneratorForSource } from "./function_dna"; +import { cardGeneratorsForSource } from "./currying"; + +export default makeScene2D(function* (view) { + const curried = createRef<CodeBlock>(); + + view.add( + <Layout direction="row" gap={100} layout> + <CodeBlock + fontSize={25} + language="typescript" + ref={curried} + code={cardGeneratorForSource} + /> + </Layout>, + ); + + yield* slideTransition(Direction.Left); + + yield* beginSlide("show function"); + + yield* curried().edit( + 1, + )`const cardGeneratorFor = (person: PersonI, type: string): (() => CardI) => { + const birthdayCardGenerator = () => birthdayCardFn(person); // closure + const valentineCardGenerator = () => valentineCardFn(person); // closure${insert( + "\n", + )} + ${insert(`const generatorForType = (type: string) => {`)} + ${insert(" ")}switch (type) { + ${insert(" ")} case "valentine": + ${insert(" ")} return valentineCardGenerator; + ${insert(" ")} case "birthday": + ${insert(" ")} return birthdayCardGenerator; + ${insert(" ")}} + + ${insert(" ")}throw new Error(type + " not implemented"); + ${insert("};\n")}}`; + + yield* beginSlide("first currying step"); + + yield* curried().edit( + 1, + )`const cardGeneratorFor = (person: PersonI, type: string): (() => CardI) => { + const birthdayCardGenerator = () => birthdayCardFn(person); // closure + const valentineCardGenerator = () => valentineCardFn(person); // closure + + const generatorForType = (type: string) => { + switch (type) { + case "valentine": + return valentineCardGenerator; + case "birthday": + return birthdayCardGenerator; + } + + throw new Error(type + " not implemented"); + };${insert("\n\n return generatorForType;")} +}`; + yield* beginSlide("second currying step"); + + yield* curried().edit(1)`const ${edit( + "cardGeneratorFor", + "cardGeneratorsFor", + )} = ${edit( + "(person: PersonI, type: string)", + "(person: PersonI)", + )}: (() => CardI) => { + const birthdayCardGenerator = () => birthdayCardFn(person); // closure + const valentineCardGenerator = () => valentineCardFn(person); // closure + + const generatorForType = (type: string) => { + switch (type) { + case "valentine": + return valentineCardGenerator; + case "birthday": + return birthdayCardGenerator; + } + + throw new Error(type + " not implemented"); + }; + + return generatorForType; +}`; + yield* beginSlide("third currying step"); + + yield* curried().edit(1)`const cardGeneratorsFor = (person: PersonI): ${edit( + "(() => CardI)", + "((type: string) => () => CardI)", + )} => { + const birthdayCardGenerator = () => birthdayCardFn(person); // closure + const valentineCardGenerator = () => valentineCardFn(person); // closure + + const generatorForType = (type: string) => { + switch (type) { + case "valentine": + return valentineCardGenerator; + case "birthday": + return birthdayCardGenerator; + } + + throw new Error(type + " not implemented"); + }; + + return generatorForType; +}`; + yield* beginSlide("fourth currying step"); + + yield* curried().edit(1)`${edit( + cardGeneratorsForSource, + `const alanCardGenerator = (type: string): (() => CardI) => { + const alan: PersonI = { + name: "Alan Turing", + birthday: new Date("06/23/1912"), + color: theme.green.hex, + }; + + return cardGeneratorFor(alan, type); +};`, + )}`; + yield* beginSlide("partial application"); + + yield* curried().selection( + [...range(7, 9, 7, 38), ...range(0, 26, 0, 40)], + 1, + ); + + yield* beginSlide("highlight"); + + yield* curried().edit( + 1, + )`const alanCardGenerator = (type: string): (() => CardI) => { + const alan: PersonI = { + name: "Alan Turing", + birthday: new Date("06/23/1912"), + color: theme.green.hex, + }; + + return cardGeneratorFor(alan, type); +};${insert(` +(alanCardGenerator("valentine")()).message === (cardGeneratorsFor(alan)("valentine")()).message;`)}`; + yield* beginSlide("show application of pa"); +}); diff --git a/src/scenes/dna.meta b/src/scenes/dna.meta new file mode 100644 index 0000000..c1ba9fb --- /dev/null +++ b/src/scenes/dna.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 659686876 +}
\ No newline at end of file diff --git a/src/scenes/dna.tsx b/src/scenes/dna.tsx new file mode 100644 index 0000000..9cb77bd --- /dev/null +++ b/src/scenes/dna.tsx @@ -0,0 +1,22 @@ +import { Video, Layout, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import mitosis from "../../public/img/cell_division.mp4"; + +export default makeScene2D(function* (view) { + const layout = createRef<Layout>(); + const vid = createRef<Video>(); + + view.add( + <Video playbackRate={4} width={900} ref={vid} src={mitosis} x={0} />, + ); + + yield* slideTransition(Direction.Left); + yield vid().play(); + yield vid().loop(true); + yield* beginSlide("show mitosis"); +}); diff --git a/src/scenes/function_dna.meta b/src/scenes/function_dna.meta new file mode 100644 index 0000000..2648f3d --- /dev/null +++ b/src/scenes/function_dna.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 4141071538 +}
\ No newline at end of file diff --git a/src/scenes/function_dna.tsx b/src/scenes/function_dna.tsx new file mode 100644 index 0000000..64098d3 --- /dev/null +++ b/src/scenes/function_dna.tsx @@ -0,0 +1,91 @@ +import { makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + all, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { PEOPLE, Person, PersonI } from "../components/person"; +import { birthdayCardFn, valentineCardFn } from "./generalized"; +import { CardI } from "./birthday_letters"; +import { FunctionBox } from "../components/function_box"; + +export const cardGeneratorFor = ( + person: PersonI, + type: string, +): (() => CardI) => { + const birthdayCardGenerator = () => birthdayCardFn(person); + const valentineCardGenerator = () => valentineCardFn(person); + + switch (type) { + case "valentine": + return valentineCardGenerator; + case "birthday": + return birthdayCardGenerator; + } + + throw new Error(type + " not implemented"); +}; + +export const cardGeneratorForSource = `const cardGeneratorFor = (person: PersonI, type: string): (() => CardI) => { + const birthdayCardGenerator = () => birthdayCardFn(person); // closure + const valentineCardGenerator = () => valentineCardFn(person); // closure + + switch (type) { + case "valentine": + return valentineCardGenerator; + case "birthday": + return birthdayCardGenerator; + } + + throw new Error(type + " not implemented"); +}`; + +export default makeScene2D(function* (view) { + const box = createRef<FunctionBox>(); + + view.add( + <FunctionBox + arity={2} + ref={box} + fn={cardGeneratorFor} + source={cardGeneratorForSource} + outputFontSize={20} + />, + ); + + yield* all( + box().reset(0.1), + box().showCode(0.5), + slideTransition(Direction.Left, 0.5), + ); + + yield* beginSlide("show code"); + + const [alan] = PEOPLE; + yield* box().setInputs( + [{ val: alan, node: <Person person={alan} /> }, { val: "valentine" }], + 0.5, + ); + + yield* beginSlide("show inputs"); + + yield* box().hideCode(0.5); + yield* box().propogateInput(0.5); + yield* box().propogateOutput(0.5); + + yield* beginSlide("create child function"); + + const child = box().getChild(); + yield* child().showCode(0.5); + + yield* beginSlide("show child function"); + + yield* child().hideCode(0.5); + yield* child().setInputs([{ val: "" }], 0.5); + yield* child().propogateInput(0.5); + yield* child().propogateOutput(0.5); + + yield* beginSlide("propogate child function"); +}); diff --git a/src/scenes/further.meta b/src/scenes/further.meta new file mode 100644 index 0000000..bc7d625 --- /dev/null +++ b/src/scenes/further.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 60068077 +}
\ No newline at end of file diff --git a/src/scenes/further.tsx b/src/scenes/further.tsx new file mode 100644 index 0000000..8758080 --- /dev/null +++ b/src/scenes/further.tsx @@ -0,0 +1,43 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const goingFurtherLInes = [ + "pattern matching", + "the typed lambda calculus", + "church turing thesis", + "lazy vs eager loading, why we use left innermost reduction", + "compiling to machine code & continuation passing style as IR", + "monads", +]; + +export default makeScene2D(function* (view) { + const lines = createRef<Txt>(); + + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + Going Further + </Txt> + <Txt + ref={lines} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("Going Further"); + + for (const line of goingFurtherLInes) { + yield* lines().text(lines().text() + "\n\n" + line, 1); + yield* beginSlide("line - " + line); + } +}); diff --git a/src/scenes/generalized.tsx b/src/scenes/generalized.tsx index 67cbb31..a3cc841 100644 --- a/src/scenes/generalized.tsx +++ b/src/scenes/generalized.tsx @@ -1,4 +1,4 @@ -import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { Layout, makeScene2D } from "@motion-canvas/2d"; import { Direction, all, @@ -11,7 +11,7 @@ import { FunctionBox } from "../components/function_box"; import { PEOPLE, Person, PersonI } from "../components/person"; import { CardI, daysUntilNextDate } from "./birthday_letters"; -const valentineCardFn = (person: PersonI): CardI => { +export const valentineCardFn = (person: PersonI): CardI => { const valentinesDay = new Date("02/14/2024"); const message = `Dear, ${person.name}\n.` + @@ -21,7 +21,7 @@ const valentineCardFn = (person: PersonI): CardI => { return { message, deliverInDays }; }; -const birthdayCardFn = (person: PersonI): CardI => { +export const birthdayCardFn = (person: PersonI): CardI => { const age = new Date().getFullYear() - person.birthday.getFullYear(); const ending = ({ 1: "st", 2: "nd", 3: "rd" } as Record<number, string>)[ diff --git a/src/scenes/impostor.meta b/src/scenes/impostor.meta new file mode 100644 index 0000000..ab81c2f --- /dev/null +++ b/src/scenes/impostor.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 675349706 +}
\ No newline at end of file diff --git a/src/scenes/impostor.tsx b/src/scenes/impostor.tsx new file mode 100644 index 0000000..830178a --- /dev/null +++ b/src/scenes/impostor.tsx @@ -0,0 +1,134 @@ +import { Img, Layout, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, + all, +} from "@motion-canvas/core"; +import { + CodeBlock, + edit, + insert, + lines, +} from "@motion-canvas/2d/lib/components/CodeBlock"; +import amogusSus from "../../public/amogus.png"; + +const cardBuilder = `const buildCards = ( + people: PersonI[], + cardGenerator: (person: PersonI) => CardI, +): CardI[] => { + const cards: CardI[] = []; + + for (const person of people) { + const card = cardGenerator(person); + cards.push(card); + } + + return cards; +};`; + +export default makeScene2D(function* (view) { + const layout = createRef<Layout>(); + + const buildCards = createRef<CodeBlock>(); + const amogus = createRef<Img>(); + + view.add( + <Layout ref={layout} layout direction="row" gap={0}> + <CodeBlock + fontSize={25} + language="typescript" + ref={buildCards} + code={cardBuilder} + /> + <Img ref={amogus} src={amogusSus} opacity={0} width={0} height={0} /> + </Layout>, + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("show buildCards"); + + yield* buildCards().selection([...lines(6), ...lines(8)], 0.75); + yield* all( + amogus().width(300, 0.5), + amogus().height(400, 0.5), + + amogus().opacity(1, 0.5), + layout().gap(100, 0.5), + ); + + yield* beginSlide("show side effects"); + + yield* all( + buildCards().edit(1.2)`const buildCards = ( + people: PersonI[], + cardGenerator: (person: PersonI) => CardI, +): CardI[] => {${insert(` + if (people.length === 0) { + return []; + } +`)} + const cards: CardI[] = []; + + for (const person of people) { + const card = cardGenerator(person); + cards.push(card); + } + + return cards; +};`, + amogus().width(0, 0.3), + amogus().height(0, 0.3), + + layout().gap(0, 0.3), + ); + yield* beginSlide("base case"); + + yield* buildCards().edit(1.2)`const buildCards = ( + people: PersonI[], + cardGenerator: (person: PersonI) => CardI, +): CardI[] => { + if (people.length === 0) { + return []; + } + + ${edit( + "const cards: CardI[] = [];", + `const person = people[0]; + const card = cardGenerator(person);`, + )} + + for (const person of people) { + const card = cardGenerator(person); + cards.push(card); + } + + return cards; +};`; + yield* beginSlide("first card"); + + yield* buildCards().edit(1.2)`const buildCards = ( + people: PersonI[], + cardGenerator: (person: PersonI) => CardI, +): CardI[] => { + if (people.length === 0) { + return []; + } + + const person = people[0]; + const card = cardGenerator(person); + + ${edit( + `for (const person of people) { + const card = cardGenerator(person); + cards.push(card); + }`, + `const restPeople = people.slice(1); + const cards = [card].concat(buildCards(restPeople, cardGenerator));`, + )} + + return cards; +};`; + yield* beginSlide("recursion"); +}); diff --git a/src/scenes/index.ts b/src/scenes/index.ts index 6f09c88..1a5c5f8 100644 --- a/src/scenes/index.ts +++ b/src/scenes/index.ts @@ -10,18 +10,54 @@ import valentines_letters from "./valentines_letters?scene"; import birthday_letters from "./birthday_letters?scene"; import sad_people from "./sad_people?scene"; import generalized from "./generalized?scene"; +import dna from "./dna?scene"; +import function_dna from "./function_dna?scene"; +import currying from "./currying?scene"; +import currying_detail from "./currying_detail?scene"; +import impostor from "./impostor?scene"; +import pros_cons from "./pros_cons?scene"; +import parttwo from "./parttwo?scene"; +import the_lambda_calculus from "./the_lambda_calculus?scene"; +import reductions from "./reductions?scene"; +import substitution from "./substitution?scene"; +import lambda_reduction_example from "./lambda_reduction_example?scene"; +import church_encoding from "./church_encoding?scene"; +import boolean_algebra_lambda from "./boolean_algebra_lambda?scene"; +import boolean_encoding from "./boolean_encoding?scene"; +import recursion from "./recursion?scene"; +import lambda_recursion from "./lambda_recursion?scene"; +import further from "./further?scene"; +import questions from "./questions?scene"; export const scenes = [ - //title, - //me, - //partone, - //flirtingwithfunctions, - //doctor, - //first_box, - //hungry_partner, - //pure_functions, - //valentines_letters, - //sad_people, - //birthday_letters, + title, + me, + partone, + flirtingwithfunctions, + doctor, + first_box, + hungry_partner, + pure_functions, + valentines_letters, + sad_people, + birthday_letters, generalized, + dna, + function_dna, + currying, + currying_detail, + impostor, + pros_cons, + parttwo, + the_lambda_calculus, + reductions, + substitution, + church_encoding, + lambda_reduction_example, + boolean_encoding, + boolean_algebra_lambda, + recursion, + lambda_recursion, + further, + questions, ]; diff --git a/src/scenes/lambda_recursion.meta b/src/scenes/lambda_recursion.meta new file mode 100644 index 0000000..35466b8 --- /dev/null +++ b/src/scenes/lambda_recursion.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 1988478153 +}
\ No newline at end of file diff --git a/src/scenes/lambda_recursion.tsx b/src/scenes/lambda_recursion.tsx new file mode 100644 index 0000000..4a2b4a1 --- /dev/null +++ b/src/scenes/lambda_recursion.tsx @@ -0,0 +1,45 @@ +import { Layout, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { LambdaReducer } from "../components/lambda_reducer"; +import { baseDefinitions } from "../utils/lambdas"; + +export default makeScene2D(function* (view) { + const lambdaReducer = createRef<LambdaReducer>(); + const layout = createRef<Layout>(); + + view.add( + <Layout + layout + ref={layout} + direction="column" + alignItems="center" + gap={50} + ></Layout>, + ); + yield* slideTransition(Direction.Right); + yield* beginSlide("Boolean Reductions"); + + for (const term of ["Y", "(Y (λ y . y))"]) { + yield* layout().opacity(0, 0.5); + layout().add( + <LambdaReducer + ref={lambdaReducer} + lambdaTerm={term} + definitions={baseDefinitions} + ></LambdaReducer>, + ); + yield* layout().opacity(1, 0.5); + + yield* beginSlide("Next Reduction " + term); + for (let i = 0; i < 6; i++) { + yield* lambdaReducer().step(0.5); + yield* beginSlide(term + " Next Step " + i); + } + layout().removeChildren(); + } +}); diff --git a/src/scenes/lambda_reduction_example.meta b/src/scenes/lambda_reduction_example.meta new file mode 100644 index 0000000..eeefd28 --- /dev/null +++ b/src/scenes/lambda_reduction_example.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2126031881 +}
\ No newline at end of file diff --git a/src/scenes/lambda_reduction_example.tsx b/src/scenes/lambda_reduction_example.tsx new file mode 100644 index 0000000..8f2436a --- /dev/null +++ b/src/scenes/lambda_reduction_example.tsx @@ -0,0 +1,47 @@ +import { Layout, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { LambdaReducer } from "../components/lambda_reducer"; +import { baseDefinitions } from "../utils/lambdas"; + +export default makeScene2D(function* (view) { + const lambdaReducer = createRef<LambdaReducer>(); + const layout = createRef<Layout>(); + + view.add( + <Layout layout ref={layout} direction="column" alignItems="center" gap={50}> + <LambdaReducer + ref={lambdaReducer} + lambdaTerm={"(succ zero)"} + definitions={baseDefinitions} + ></LambdaReducer> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("Example Reductions"); + + for (let i = 0; !lambdaReducer().isDone(); i++) { + yield* lambdaReducer().step(0.5); + yield* beginSlide("1 Next Step " + i); + } + + const one = lambdaReducer().getCode(); + const reduceToTwo = createRef<LambdaReducer>(); + layout().add( + <LambdaReducer + ref={reduceToTwo} + lambdaTerm={`(succ ${one})`} + definitions={baseDefinitions} + ></LambdaReducer> + ); + + for (let i = 0; !reduceToTwo().isDone(); i++) { + yield* reduceToTwo().step(0.5); + yield* beginSlide("2 Next Step " + i); + } +}); diff --git a/src/scenes/me.tsx b/src/scenes/me.tsx index 1d819e3..143d131 100644 --- a/src/scenes/me.tsx +++ b/src/scenes/me.tsx @@ -1,7 +1,7 @@ import { Node, Img, Txt, Layout, makeScene2D } from "@motion-canvas/2d"; import { beginSlide, createRef, all } from "@motion-canvas/core"; -import me from "../../public/img/me.jpg"; +import pengy from "../../public/img/pengy.png"; import { theme } from "../theme"; export default makeScene2D(function* (view) { @@ -41,11 +41,11 @@ export default makeScene2D(function* (view) { </Txt> </Node> </Layout> - <Img y={-10} ref={img} src={me} width={10} alpha={0} radius={20} />{" "} + <Img y={-10} ref={img} src={pengy} width={10} alpha={0} radius={20} />{" "} <Txt opacity={0} ref={src} fontFamily={theme.font} fill={theme.green.hex}> git.simponic.xyz/simponic/compiling-the-lambda-calculus </Txt> - </>, + </> ); yield img().fill(img().getColorAtPoint(0)); @@ -59,7 +59,7 @@ export default makeScene2D(function* (view) { node().opacity(1, 1), layout().position.x(diff, 1), src().opacity(1, 1), - src().position.y(290, 1), + src().position.y(290, 1) ); yield* beginSlide("About Me"); diff --git a/src/scenes/parttwo.meta b/src/scenes/parttwo.meta new file mode 100644 index 0000000..c18d436 --- /dev/null +++ b/src/scenes/parttwo.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2908089933 +}
\ No newline at end of file diff --git a/src/scenes/parttwo.tsx b/src/scenes/parttwo.tsx new file mode 100644 index 0000000..eb62e09 --- /dev/null +++ b/src/scenes/parttwo.tsx @@ -0,0 +1,16 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { Direction, beginSlide, slideTransition } from "@motion-canvas/core"; +import { theme } from "../theme"; + +export default makeScene2D(function* (view) { + yield view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontFamily={theme.font} fontSize={100} fill={theme.text.hex}> + Part Two + </Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("Part Two"); +}); diff --git a/src/scenes/pros_cons.meta b/src/scenes/pros_cons.meta new file mode 100644 index 0000000..128b02e --- /dev/null +++ b/src/scenes/pros_cons.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 3275339858 +}
\ No newline at end of file diff --git a/src/scenes/pros_cons.tsx b/src/scenes/pros_cons.tsx new file mode 100644 index 0000000..508c7bc --- /dev/null +++ b/src/scenes/pros_cons.tsx @@ -0,0 +1,61 @@ +import { Img, Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const PROS = [ + "readbility, reasoning", + "concurrency", + "no side effects", + "computers and math!", +]; + +const CONS = ["more computation", "higher learning curve"]; + +export default makeScene2D(function* (view) { + const pros = createRef<Txt>(); + const cons = createRef<Txt>(); + + view.add( + <Layout direction="row" justifyContent="center" gap={300} layout> + <Layout direction="column" justifyContent="end"> + <Txt fontSize={30} fontFamily={theme.font} fill={theme.green.hex}> + PROS :) + </Txt> + <Txt + ref={pros} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + <Layout direction="column" justifyContent="start"> + <Txt fontSize={30} fontFamily={theme.font} fill={theme.red.hex}> + CONS :( + </Txt> + <Txt + ref={cons} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + </Layout>, + ); + yield* slideTransition(Direction.Right); + yield* beginSlide("layout pros and cons"); + + for (const pro of PROS) { + yield* pros().text(pros().text() + "\n\n+ " + pro, 0.5); + yield* beginSlide("pro - " + pro); + } + + for (const con of CONS) { + yield* cons().text(cons().text() + "\n\n- " + con, 0.5); + yield* beginSlide("con - " + con); + } +}); diff --git a/src/scenes/questions.meta b/src/scenes/questions.meta new file mode 100644 index 0000000..c6cc2f9 --- /dev/null +++ b/src/scenes/questions.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 3904825059 +}
\ No newline at end of file diff --git a/src/scenes/questions.tsx b/src/scenes/questions.tsx new file mode 100644 index 0000000..16adf54 --- /dev/null +++ b/src/scenes/questions.tsx @@ -0,0 +1,16 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { Direction, beginSlide, slideTransition } from "@motion-canvas/core"; +import { theme } from "../theme"; + +export default makeScene2D(function* (view) { + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + Questions? + </Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("Questions"); +}); diff --git a/src/scenes/recursion.meta b/src/scenes/recursion.meta new file mode 100644 index 0000000..b574f39 --- /dev/null +++ b/src/scenes/recursion.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 693500437 +}
\ No newline at end of file diff --git a/src/scenes/recursion.tsx b/src/scenes/recursion.tsx new file mode 100644 index 0000000..167dd00 --- /dev/null +++ b/src/scenes/recursion.tsx @@ -0,0 +1,36 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const recursion = ["Y = λ f . (λ x . f (x x)) (λ x . f (x x))"]; + +export default makeScene2D(function* (view) { + const lines = createRef<Txt>(); + + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + Recursion and Combinators + </Txt> + <Txt + ref={lines} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("The Lambda Calculus - Church Encoding"); + + for (const line of recursion) { + yield* lines().text(lines().text() + "\n\n" + line, 1); + yield* beginSlide("recursion - " + line); + } +}); diff --git a/src/scenes/reductions.meta b/src/scenes/reductions.meta new file mode 100644 index 0000000..6c4e6c7 --- /dev/null +++ b/src/scenes/reductions.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 2906227318 +}
\ No newline at end of file diff --git a/src/scenes/reductions.tsx b/src/scenes/reductions.tsx new file mode 100644 index 0000000..5ee8961 --- /dev/null +++ b/src/scenes/reductions.tsx @@ -0,0 +1,40 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const reductions = [ + "1. α - conversion: Renaming of bound variables to avoid name clashes (out of\nscope - assume user knows not to bind variable names already chosen elsewhere).", + "2. β - reduction: Application of a function to an argument.", + "3. η - reduction: Conversion of a function to a point-free form (out of scope).", +]; + +export default makeScene2D(function* (view) { + const rules = createRef<Txt>(); + + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + The Lambda Calculus - Reductions + </Txt> + <Txt + ref={rules} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("The Lambda Calculus - Reductions"); + + for (const rule of reductions) { + yield* rules().text(rules().text() + "\n\n" + rule, 1); + yield* beginSlide("reduction - " + rule); + } +}); diff --git a/src/scenes/substitution.meta b/src/scenes/substitution.meta new file mode 100644 index 0000000..56299b4 --- /dev/null +++ b/src/scenes/substitution.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 3113568447 +}
\ No newline at end of file diff --git a/src/scenes/substitution.tsx b/src/scenes/substitution.tsx new file mode 100644 index 0000000..1e7e48c --- /dev/null +++ b/src/scenes/substitution.tsx @@ -0,0 +1,45 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const substitution = [ + "β-reduce [ (λ x . x) y ] => y\n\n", + "Formal definition:", + "1. x[x := N] = N", + "2. y[x := N] = y if y != x", + "3. (M N)[x := P] = (M[x := P]) (N[x := P])", + "4. (λ x . M)[x := N] = λ x . M", + "5. (λ y . M)[x := N] = λ y . (M[x := N]) if y != x and y is not _free_ in N", + " +=> A variable is _free_ in a lambda term if it is not bound by a λ abstraction.", +]; + +export default makeScene2D(function* (view) { + const rules = createRef<Txt>(); + + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + The Lambda Calculus - Substitution Rules + </Txt> + <Txt + ref={rules} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("The Lambda Calculus - Substitutions"); + + for (const rule of substitution) { + yield* rules().text(rules().text() + "\n\n" + rule, 1); + yield* beginSlide("substitution - " + rule); + } +}); diff --git a/src/scenes/the_lambda_calculus.meta b/src/scenes/the_lambda_calculus.meta new file mode 100644 index 0000000..56b46d0 --- /dev/null +++ b/src/scenes/the_lambda_calculus.meta @@ -0,0 +1,5 @@ +{ + "version": 0, + "timeEvents": [], + "seed": 561758562 +}
\ No newline at end of file diff --git a/src/scenes/the_lambda_calculus.tsx b/src/scenes/the_lambda_calculus.tsx new file mode 100644 index 0000000..7a3e692 --- /dev/null +++ b/src/scenes/the_lambda_calculus.tsx @@ -0,0 +1,40 @@ +import { Layout, Txt, makeScene2D } from "@motion-canvas/2d"; +import { + Direction, + beginSlide, + createRef, + slideTransition, +} from "@motion-canvas/core"; +import { theme } from "../theme"; + +const lambdaRules = [ + '1. "x": A variable is a character or string representing a parameter, and is a valid lambda term.', + '2. "(λ x . t)" is an "abstraction" - a function definition, taking as input the \nbound variable x and returning the lambda term t.', + '3. (M N) is an "application", applying a lambda term M with a lambda term N.', +]; + +export default makeScene2D(function* (view) { + const rules = createRef<Txt>(); + + view.add( + <Layout layout direction="column" alignItems="center"> + <Txt fontSize={40} fontFamily={theme.font} fill={theme.text.hex}> + The Lambda Calculus + </Txt> + <Txt + ref={rules} + fontSize={30} + fontFamily={theme.font} + fill={theme.text.hex} + ></Txt> + </Layout> + ); + + yield* slideTransition(Direction.Right); + yield* beginSlide("The Lambda Calculus"); + + for (const rule of lambdaRules) { + yield* rules().text(rules().text() + "\n\n" + rule, 1); + yield* beginSlide("rule - " + rule); + } +}); |