Merge pull request #221 from QURIresearch/ts-interface-typing
Ts interface typing
This commit is contained in:
commit
abb41871d7
3
packages/squiggle-lang/.prettierignore
Normal file
3
packages/squiggle-lang/.prettierignore
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.bs.js
|
||||
*.gen.tsx
|
||||
dist
|
|
@ -1,7 +1,9 @@
|
|||
# Squiggle language
|
||||
|
||||
## Build for development
|
||||
|
||||
We assume that you ran `yarn` at the monorepo level.
|
||||
|
||||
```sh
|
||||
yarn build
|
||||
```
|
||||
|
@ -9,6 +11,7 @@ yarn build
|
|||
`yarn bundle` is needed for a deployment.
|
||||
|
||||
Other:
|
||||
|
||||
```sh
|
||||
yarn start # listens to files and recompiles at every mutation
|
||||
yarn test
|
||||
|
@ -19,6 +22,7 @@ yarn coverage; o _coverage/index.html # produces coverage report and opens it i
|
|||
```
|
||||
|
||||
## Information
|
||||
|
||||
Squiggle is a language for representing probability distributions, as well as functions that return probability distributions. Its original intended use is for improving epistemics around EA decisions.
|
||||
|
||||
This package, `@quri/squiggle-lang`, contains the core language of squiggle. The main feature revolves around evaluating squiggle expressions. Currently the package only exports a single function, named "run", which from a squiggle string returns an object representing the result of the evaluation.
|
||||
|
@ -32,7 +36,9 @@ ReScript has an interesting philosophy of not providing much in the way of effec
|
|||
`.gen.ts` files are created by the [`@genType`](https://rescript-lang.org/docs/gentype/latest/getting-started) decorator, which creates typescript typings for needed parts of the codebase so that they can be easily used in typescript. These .gen.ts files reference the .bs.js files generated by rescript.
|
||||
|
||||
### Errors regarding the `rationale` package
|
||||
|
||||
You may notice sometimes, that there are errors about the `rationale` package. If you ever get these errors, `yarn build` should fix this issue. These errors occur because `yarn build` also needs to create build files that are in `node_modules`. So if you replace `node_modules` you may need to rebuild to get those files back.
|
||||
|
||||
## Distributing this package or using this package from other monorepo packages
|
||||
|
||||
As it says in the other `packages/*/README.md`s, building this package is an essential step of building other packages.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { run, GenericDist, resultMap, makeSampleSetDist } from "../src/js/index";
|
||||
import { run, Distribution, resultMap } from "../src/js/index";
|
||||
|
||||
let testRun = (x: string) => {
|
||||
let result = run(x);
|
||||
|
@ -9,6 +9,10 @@ let testRun = (x: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
function Ok<b>(x: b) {
|
||||
return { tag: "Ok", value: x };
|
||||
}
|
||||
|
||||
describe("Simple calculations and results", () => {
|
||||
test("mean(normal(5,2))", () => {
|
||||
expect(testRun("mean(normal(5,2))")).toEqual({
|
||||
|
@ -38,16 +42,15 @@ describe("Multimodal too many weights error", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("GenericDist", () => {
|
||||
|
||||
describe("Distribution", () => {
|
||||
//It's important that sampleCount is less than 9. If it's more, than that will create randomness
|
||||
//Also, note, the value should be created using makeSampleSetDist() later on.
|
||||
let env = { sampleCount: 8, xyPointLength: 100 };
|
||||
let dist = new GenericDist(
|
||||
let dist = new Distribution(
|
||||
{ tag: "SampleSet", value: [3, 4, 5, 6, 6, 7, 10, 15, 30] },
|
||||
env
|
||||
);
|
||||
let dist2 = new GenericDist(
|
||||
let dist2 = new Distribution(
|
||||
{ tag: "SampleSet", value: [20, 22, 24, 29, 30, 35, 38, 44, 52] },
|
||||
env
|
||||
);
|
||||
|
@ -66,22 +69,24 @@ describe("GenericDist", () => {
|
|||
});
|
||||
test("toPointSet", () => {
|
||||
expect(
|
||||
resultMap(dist.toPointSet(), (r: GenericDist) => r.toString()).value.value
|
||||
).toBe("Point Set Distribution");
|
||||
resultMap(dist.toPointSet(), (r: Distribution) => r.toString()).value
|
||||
).toEqual(Ok("Point Set Distribution"));
|
||||
});
|
||||
test("toSparkline", () => {
|
||||
expect(dist.toSparkline(20).value).toBe("▁▁▃▅███▆▄▃▂▁▁▂▂▃▂▁▁▁");
|
||||
expect(dist.toSparkline(20).value).toEqual("▁▁▃▅███▆▄▃▂▁▁▂▂▃▂▁▁▁");
|
||||
});
|
||||
test("algebraicAdd", () => {
|
||||
expect(
|
||||
resultMap(dist.algebraicAdd(dist2), (r: GenericDist) => r.toSparkline(20))
|
||||
.value.value
|
||||
).toBe("▁▁▂▄▆████▇▆▄▄▃▃▃▂▁▁▁");
|
||||
resultMap(dist.algebraicAdd(dist2), (r: Distribution) =>
|
||||
r.toSparkline(20)
|
||||
).value
|
||||
).toEqual(Ok("▁▁▂▄▆████▇▆▄▄▃▃▃▂▁▁▁"));
|
||||
});
|
||||
test("pointwiseAdd", () => {
|
||||
expect(
|
||||
resultMap(dist.pointwiseAdd(dist2), (r: GenericDist) => r.toSparkline(20))
|
||||
.value.value
|
||||
).toBe("▁▂▅██▅▅▅▆▇█▆▅▃▃▂▂▁▁▁");
|
||||
resultMap(dist.pointwiseAdd(dist2), (r: Distribution) =>
|
||||
r.toSparkline(20)
|
||||
).value
|
||||
).toEqual(Ok("▁▂▅██▅▅▅▆▇█▆▅▃▃▂▂▁▁▁"));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,11 +11,7 @@
|
|||
"subdirs": true
|
||||
}
|
||||
],
|
||||
"bsc-flags": [
|
||||
"-bs-super-errors",
|
||||
"-bs-no-version-header",
|
||||
"-bs-g"
|
||||
],
|
||||
"bsc-flags": ["-bs-super-errors", "-bs-no-version-header", "-bs-g"],
|
||||
"package-specs": [
|
||||
{
|
||||
"module": "commonjs",
|
||||
|
@ -44,10 +40,6 @@
|
|||
"number": "+A-42-48-9-30-4-102-20-27-41"
|
||||
},
|
||||
"ppx-flags": [
|
||||
[
|
||||
"../../node_modules/bisect_ppx/ppx",
|
||||
"--exclude-files",
|
||||
".*_test\\.res$$"
|
||||
]
|
||||
["../../node_modules/bisect_ppx/ppx", "--exclude-files", ".*_test\\.res$$"]
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,13 +7,7 @@ import type {
|
|||
} from "../rescript/ProgramEvaluator.gen";
|
||||
export type { SamplingInputs, exportEnv, exportDistribution };
|
||||
export type { t as DistPlus } from "../rescript/OldInterpreter/DistPlus.gen";
|
||||
import {
|
||||
genericDist,
|
||||
env,
|
||||
resultDist,
|
||||
resultFloat,
|
||||
resultString,
|
||||
} from "../rescript/TypescriptInterface.gen";
|
||||
import { genericDist, env, error } from "../rescript/TypescriptInterface.gen";
|
||||
export { makeSampleSetDist } from "../rescript/TypescriptInterface.gen";
|
||||
import {
|
||||
Constructors_mean,
|
||||
|
@ -52,7 +46,7 @@ export function run(
|
|||
squiggleString: string,
|
||||
samplingInputs?: SamplingInputs,
|
||||
environment?: exportEnv
|
||||
): { tag: "Ok"; value: exportType } | { tag: "Error"; value: string } {
|
||||
): result<exportType, string> {
|
||||
let si: SamplingInputs = samplingInputs
|
||||
? samplingInputs
|
||||
: defaultSamplingInputs;
|
||||
|
@ -60,19 +54,20 @@ export function run(
|
|||
return runAll(squiggleString, si, env);
|
||||
}
|
||||
|
||||
//This is clearly not fully typed. I think later we should use a functional library to
|
||||
// provide a better Either type and corresponding functions.
|
||||
type result =
|
||||
type result<a, b> =
|
||||
| {
|
||||
tag: "Ok";
|
||||
value: any;
|
||||
value: a;
|
||||
}
|
||||
| {
|
||||
tag: "Error";
|
||||
value: any;
|
||||
value: b;
|
||||
};
|
||||
|
||||
export function resultMap(r: result, mapFn: any): result {
|
||||
export function resultMap<a, b, c>(
|
||||
r: result<a, c>,
|
||||
mapFn: (x: a) => b
|
||||
): result<b, c> {
|
||||
if (r.tag === "Ok") {
|
||||
return { tag: "Ok", value: mapFn(r.value) };
|
||||
} else {
|
||||
|
@ -80,11 +75,11 @@ export function resultMap(r: result, mapFn: any): result {
|
|||
}
|
||||
}
|
||||
|
||||
export function resultExn(r: result): any {
|
||||
r.value
|
||||
export function resultExn<a, c>(r: result<a, c>): a | c {
|
||||
return r.value;
|
||||
}
|
||||
|
||||
export class GenericDist {
|
||||
export class Distribution {
|
||||
t: genericDist;
|
||||
env: env;
|
||||
|
||||
|
@ -94,133 +89,133 @@ export class GenericDist {
|
|||
return this;
|
||||
}
|
||||
|
||||
mapResultDist(r: resultDist) {
|
||||
return resultMap(r, (v: genericDist) => new GenericDist(v, this.env));
|
||||
mapResultDist(r: result<genericDist, error>): result<Distribution, error> {
|
||||
return resultMap(r, (v: genericDist) => new Distribution(v, this.env));
|
||||
}
|
||||
|
||||
mean() {
|
||||
mean(): result<number, error> {
|
||||
return Constructors_mean({ env: this.env }, this.t);
|
||||
}
|
||||
|
||||
sample(): resultFloat {
|
||||
sample(): result<number, error> {
|
||||
return Constructors_sample({ env: this.env }, this.t);
|
||||
}
|
||||
|
||||
pdf(n: number): resultFloat {
|
||||
pdf(n: number): result<number, error> {
|
||||
return Constructors_pdf({ env: this.env }, this.t, n);
|
||||
}
|
||||
|
||||
cdf(n: number): resultFloat {
|
||||
cdf(n: number): result<number, error> {
|
||||
return Constructors_cdf({ env: this.env }, this.t, n);
|
||||
}
|
||||
|
||||
inv(n: number): resultFloat {
|
||||
inv(n: number): result<number, error> {
|
||||
return Constructors_inv({ env: this.env }, this.t, n);
|
||||
}
|
||||
|
||||
normalize() {
|
||||
normalize(): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_normalize({ env: this.env }, this.t)
|
||||
);
|
||||
}
|
||||
|
||||
toPointSet() {
|
||||
toPointSet(): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_toPointSet({ env: this.env }, this.t)
|
||||
);
|
||||
}
|
||||
|
||||
toSampleSet(n: number) {
|
||||
toSampleSet(n: number): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_toSampleSet({ env: this.env }, this.t, n)
|
||||
);
|
||||
}
|
||||
|
||||
truncate(left: number, right: number) {
|
||||
truncate(left: number, right: number): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_truncate({ env: this.env }, this.t, left, right)
|
||||
);
|
||||
}
|
||||
|
||||
inspect() {
|
||||
inspect(): result<Distribution, error> {
|
||||
return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
|
||||
}
|
||||
|
||||
toString(): resultString {
|
||||
toString(): result<string, error> {
|
||||
return Constructors_toString({ env: this.env }, this.t);
|
||||
}
|
||||
|
||||
toSparkline(n: number): resultString {
|
||||
toSparkline(n: number): result<string, error> {
|
||||
return Constructors_toSparkline({ env: this.env }, this.t, n);
|
||||
}
|
||||
|
||||
algebraicAdd(d2: GenericDist) {
|
||||
algebraicAdd(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_algebraicAdd({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
algebraicMultiply(d2: GenericDist) {
|
||||
algebraicMultiply(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_algebraicMultiply({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
algebraicDivide(d2: GenericDist) {
|
||||
algebraicDivide(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_algebraicDivide({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
algebraicSubtract(d2: GenericDist) {
|
||||
algebraicSubtract(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_algebraicSubtract({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
algebraicLogarithm(d2: GenericDist) {
|
||||
algebraicLogarithm(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_algebraicLogarithm({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
algebraicPower(d2: GenericDist) {
|
||||
algebraicPower(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_algebraicPower({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
pointwiseAdd(d2: GenericDist) {
|
||||
pointwiseAdd(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_pointwiseAdd({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
pointwiseMultiply(d2: GenericDist) {
|
||||
pointwiseMultiply(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_pointwiseMultiply({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
pointwiseDivide(d2: GenericDist) {
|
||||
pointwiseDivide(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_pointwiseDivide({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
pointwiseSubtract(d2: GenericDist) {
|
||||
pointwiseSubtract(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_pointwiseSubtract({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
pointwiseLogarithm(d2: GenericDist) {
|
||||
pointwiseLogarithm(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_pointwiseLogarithm({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
}
|
||||
|
||||
pointwisePower(d2: GenericDist) {
|
||||
pointwisePower(d2: Distribution): result<Distribution, error> {
|
||||
return this.mapResultDist(
|
||||
Constructors_pointwisePower({ env: this.env }, this.t, d2.t)
|
||||
);
|
||||
|
|
|
@ -4,11 +4,12 @@ This library provides one interface to generic distributions. These distribution
|
|||
|
||||
Different internal formats (symbolic, point set, sample set) allow for benefits and features. It's common for distributions to be converted into either point sets or sample sets to enable certain functions.
|
||||
|
||||
In addition to this interface, there's a second, generic function, for calling functions on this generic distribution type. This ``genericOperation`` standardizes the inputs and outputs for these various function calls. See it's ``run()`` function.
|
||||
In addition to this interface, there's a second, generic function, for calling functions on this generic distribution type. This `genericOperation` standardizes the inputs and outputs for these various function calls. See it's `run()` function.
|
||||
|
||||
Performance is very important. Some operations can take a long time to run, and even then, be inaccurate. Because of this, we plan to have a lot of logging and stack tracing functionality eventually built in.
|
||||
|
||||
## Diagram of Distribution Types
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Generic Distribution] -->B{Point Set}
|
||||
|
@ -34,6 +35,7 @@ graph TD
|
|||
## Diagram of Generic Distribution Types
|
||||
|
||||
## Todo
|
||||
|
||||
- [ ] Lots of cleanup
|
||||
- [ ] Simple test story
|
||||
- [ ] Provide decent stack traces for key calls in GenericOperation. This could be very useful for debugging.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const pdfast = require('pdfast');
|
||||
const pdfast = require("pdfast");
|
||||
const _ = require("lodash");
|
||||
|
||||
const samplesToContinuousPdf = (
|
||||
|
@ -6,13 +6,17 @@ const samplesToContinuousPdf = (
|
|||
size,
|
||||
width,
|
||||
min = false,
|
||||
max = false,
|
||||
max = false
|
||||
) => {
|
||||
let _samples = _.filter(samples, _.isFinite);
|
||||
if (_.isFinite(min)) { _samples = _.filter(_samples, r => r > min) };
|
||||
if (_.isFinite(max)) { _samples = _.filter(_samples, r => r < max) };
|
||||
if (_.isFinite(min)) {
|
||||
_samples = _.filter(_samples, (r) => r > min);
|
||||
}
|
||||
if (_.isFinite(max)) {
|
||||
_samples = _.filter(_samples, (r) => r < max);
|
||||
}
|
||||
let pdf = pdfast.create(_samples, { size, width });
|
||||
return {xs: pdf.map(r => r.x), ys: pdf.map(r => r.y)};
|
||||
return { xs: pdf.map((r) => r.x), ys: pdf.map((r) => r.y) };
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
const math = require("mathjs");
|
||||
|
||||
function parseMath(f) {
|
||||
return JSON.parse(JSON.stringify(math.parse(f)))
|
||||
};
|
||||
return JSON.parse(JSON.stringify(math.parse(f)));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
parseMath,
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
const path = require('path');
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: './src/js/index.ts',
|
||||
mode: "production",
|
||||
entry: "./src/js/index.ts",
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
use: 'ts-loader',
|
||||
use: "ts-loader",
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js'],
|
||||
extensions: [".tsx", ".ts", ".js"],
|
||||
},
|
||||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: "bundle.js",
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
library: {
|
||||
name: 'squiggle_lang',
|
||||
type: 'umd',
|
||||
name: "squiggle_lang",
|
||||
type: "umd",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user