////////// Exercice 1 ////////// // A polynomial for the tests function myPolynome(x) { return 3 * x * x + 4.7; } // A first version without currying function differentiate2(h, f) { return (x) => (f(x + h) - f(x - h)) / (2 * h); } function testDiffType(aValStr, aVal, aExpected) { const res = typeof aVal == aExpected ? "OK" : "KO"; console.log(`Test type of ${aValStr} = '${aExpected}': ${res}`); } testDiffType("differentiate2(0.001, myPolynome)", differentiate2(0.001, myPolynome), "function"); testDiffType("differentiate2(0.001, myPolynome)(1)", differentiate2(0.001, myPolynome)(1), "number"); testDiffType("differentiate2(0.00001, Math.sin)", differentiate2(0.00001, Math.sin), "function"); testDiffType("differentiate2(0.00001, Math.sin)(1)", differentiate2(0.00001, Math.sin)(1), "number"); // Specialize differentiate2 on h=0.1 const specDiff2OnH = (f) => differentiate2(0.01, f); // Specialize differentiate2 on f=myPolynome const specDiff2OnF = (h) => differentiate2(h, myPolynome); function testDiffVal(aFunName, aFun, aValue, aExpected) { console.log(`Test ${aFunName}(${aValue}) = ${aFun(aValue)}, ` + `expected to be ~= ${aExpected}`); } testDiffVal("specDiff2OnH(myPolynome)", specDiff2OnH(myPolynome), 1, 6); testDiffVal("specDiff2OnF(0.01)", specDiff2OnF(0.01), 1, 6); // This solution uses anonymous functions to ease currying // It is perfectly possible to use functions instead. const differentiateCurry = (h) => (f) => (x) => (f(x+h) - f(x-h)) / (2*h); // The good thing with curryfication if that we can specialize to // directly get the derivative as a function of `x` const specCurryCos = differentiateCurry(0.1)(Math.cos); testDiffVal("specCurryCos", specCurryCos, 0., 0.); testDiffVal("specCurryCos", specCurryCos, Math.PI, 0.); const specCurrySin = differentiateCurry(0.1)(Math.sin); testDiffVal("specCurrySin", specCurrySin, 0., 1.); testDiffVal("specCurrySin", specCurrySin, Math.PI, -1.); // Specialization so that it takes a function and returns a function // approximated with `h=0.1` const specCurryDiff = (f) => differentiateCurry(0.1)(f); // Same as const diff = differentiateCurry(0.1) testDiffVal("specCurryDiff(Math.cos)", specCurryDiff(Math.cos), Math.PI/2, -1.); // Specialization so that it takes `h` and returns the derivative of // Math.cos approximated with `h` const specCurryOnH = (h) => differentiateCurry(h)(Math.cos); testDiffVal("specCurryOnH(0.05)", specCurryOnH(0.05), Math.PI/2, -1.); testDiffVal("specCurryOnH(0.005)", specCurryOnH(0.005), Math.PI/2, -1.); ////////// Exercice 2 ////////// type PointedPair = { car: T; cdr: U; }; function cons(aCar: T, aCdr: U) : PointedPair { return { car: aCar, cdr: aCdr }; } // Functions to type on pointed pairs function car(aCons) { return aCons['car']; } function cdr(aCons) { return aCons['cdr']; } /* ------------------------------- */ type List = undefined | { car: T, cdr: List }; const nil = undefined; // nil is automatically of type List function isNonEmpty(l: List): l is PointedPair> { return l !== undefined; } function isEmpty(l : List): l is undefined { return !isNonEmpty(l); } // Maps a function `f` on a list `l` function listMap(f, l) { if (isEmpty(l)) return l; else return cons(f(head(l)), listMap(f, tail(l))); } // Fold from right function listFoldR (f, init, l) { if (isEmpty(l)) return init; else { return f(listFoldR(f, init, tail(l)), head(l)); } } ////////// Exercice 3 ////////// type Person = { name: string, birth: number, death: number }; const db : Array = [ { name: "Thalès", birth: -625, death: -547 }, { name: "Anaximandre", birth: -600, death: -546 }, { name: "Héraclite", birth: -544, death: -480 }, { name: "Empédocle", birth: -490, death: -430 }, { name: "Aristote", birth: -384, death: -322 }, { name: "Archimède", birth: -287, death: -212 }, { name: "Ératosthène", birth: -276, death: -194 }, { name: "Ptolémée", birth: 100, death: 170 }, { name: "Pétrone", birth: 27, death: 66 }, { name: "Leucippe", birth: -460, death: -370 }, { name: "Démocrite", birth: -460, death: -370 }, { name: "Protagoras", birth: -490, death: -420 }, { name: "Antiphon", birth: -480, death: -410 }, { name: "Gorgias", birth: -480, death: -375 }, { name: "Aristippe", birth: -435, death: -356 }, { name: "Antisthène", birth: -444, death: -365 }, { name: "Diogène de Sinope", birth: -413, death: -327 }, { name: "Prodicos", birth: -470, death: -399 }, { name: "Eudoxe", birth: -408, death: -355 }, { name: "Épicure", birth: -331, death: -270 }, { name: "Philodème de Gadara", birth: -110, death: -40 }, { name: "Lucrèce", birth: -94, death: -55 }, { name: "Xénophane", birth: -570, death: -475 }, { name: "Zénon", birth: -490, death: -430 }, { name: "Pythagore", birth: -580, death: -495 }, { name: "Socrate", birth: -470, death: -399 }, { name: "Platon", birth: -428, death: -347 }, { name: "Xénophon", birth: -445, death: -354 }, { name: "Zénon de Cition", birth: -335, death: -263 }, { name: "Cléanthe", birth: -330, death: -232 }, { name: "Chrysippe", birth: -280, death: -206 }, { name: "Cicéron", birth: -106, death: -43 }, { name: "Sénèque", birth: 4, death: 65 }, { name: "Épictète", birth: 50, death: 130 }, { name: "Marc Aurèle", birth: 121, death: 180 }, { name: "Catulle", birth: -84, death: -54 }, { name: "Properce", birth: -47, death: 15 }, { name: "Tibulle", birth: -54, death: -19 }, { name: "Alexandre le Grand", birth: -356, death: -323 }, { name: "Jules César", birth: -100, death: -44 }, ] type Person = { name: string, birth: number, death: number }; const db : Array = [ { name: "Thales", birth: -625, death: -547 }, { name: "Anaximandre", birth: -600, death: -546 }, { name: "Heraclite", birth: -544, death: -480 }, ]