Cleanup of SampleSet map

This commit is contained in:
Ozzie Gooen 2022-05-27 09:40:49 -04:00
parent d3a2f391a7
commit 0da95bd21e
5 changed files with 24 additions and 33 deletions

View File

@ -281,7 +281,7 @@ module AlgebraicCombination = {
let fn = Operation.Algebraic.toFn(arithmeticOperation) let fn = Operation.Algebraic.toFn(arithmeticOperation)
E.R.merge(toSampleSet(t1), toSampleSet(t2)) E.R.merge(toSampleSet(t1), toSampleSet(t2))
->E.R.bind(((t1, t2)) => { ->E.R.bind(((t1, t2)) => {
SampleSetDist.map2(~fn, ~t1, ~t2)->E.R2.errMap(x => DistributionTypes.OperationError(x)) SampleSetDist.map2(~fn, ~t1, ~t2)->E.R2.errMap(x => DistributionTypes.SampleSetError(x))
}) })
->E.R2.fmap(r => DistributionTypes.SampleSet(r)) ->E.R2.fmap(r => DistributionTypes.SampleSet(r))
} }

View File

@ -20,6 +20,14 @@ module Error = {
} }
let fromOperationError = e => OperationError(e) let fromOperationError = e => OperationError(e)
let toString = (err: sampleSetError) => {
switch(err){
| TooFewSamples => "Too few samples when constructing sample set"
| NonNumericInput(err) => `Found a non-number in input: ${err}`
| OperationError(err) => Operation.Error.toString(err)
}
}
} }
include Error include Error
@ -87,48 +95,27 @@ let sampleN = (t: t, n) => {
} }
} }
let _fromSampleResultArray = (samples: array<result<float, QuriSquiggleLang.Operation.Error.t>>) =>
E.A.R.firstErrorOrOpen(samples)->E.R2.errMap(Error.fromOperationError) |> E.R2.bind(make)
let samplesMap = (~fn: float => result<float, Operation.Error.t>, t: t): result< let samplesMap = (~fn: float => result<float, Operation.Error.t>, t: t): result<
t, t,
sampleSetError, sampleSetError,
> => { > => T.get(t)->E.A2.fmap(fn)->_fromSampleResultArray
let samples = T.get(t)->E.A2.fmap(fn)
E.A.R.firstErrorOrOpen(samples)->E.R2.errMap(Error.fromOperationError) |> E.R2.bind(make)
}
//TODO: Figure out what to do if distributions are different lengths. ``zip`` is kind of inelegant for this. //TODO: Figure out what to do if distributions are different lengths. ``zip`` is kind of inelegant for this.
let map2 = (~fn: (float, float) => result<float, Operation.Error.t>, ~t1: t, ~t2: t): result< let map2 = (~fn: (float, float) => result<float, Operation.Error.t>, ~t1: t, ~t2: t): result<
t, t,
Operation.Error.t, sampleSetError,
> => { > => E.A.zip(get(t1), get(t2))->E.A2.fmap(E.Tuple2.toFnCall(fn))->_fromSampleResultArray
let samples = E.A.zip(get(t1), get(t2))->E.A2.fmap(((a, b)) => fn(a, b))
// This assertion should never be reached. In order for it to be reached, one
// of the input parameters would need to be a sample set distribution with less
// than 6 samples. Which should be impossible due to the smart constructor.
// I could prove this to the type system (say, creating a {first: float, second: float, ..., fifth: float, rest: array<float>}
// But doing so would take too much time, so I'll leave it as an assertion
E.A.R.firstErrorOrOpen(samples)->E.R2.fmap(x =>
E.R.toExnFnString(Error.sampleSetErrorToString, make(x))
)
}
let map3 = ( let map3 = (
~fn: (float, float, float) => result<float, Operation.Error.t>, ~fn: (float, float, float) => result<float, Operation.Error.t>,
~t1: t, ~t1: t,
~t2: t, ~t2: t,
~t3: t, ~t3: t,
): result<t, Operation.Error.t> => { ): result<t, sampleSetError> =>
let samples = E.A.zip3(get(t1), get(t2), get(t3))->E.A2.fmap(((a, b, c)) => fn(a, b, c)) E.A.zip3(get(t1), get(t2), get(t3))->E.A2.fmap(E.Tuple3.toFnCall(fn))->_fromSampleResultArray
// This assertion should never be reached. In order for it to be reached, one
// of the input parameters would need to be a sample set distribution with less
// than 6 samples. Which should be impossible due to the smart constructor.
// I could prove this to the type system (say, creating a {first: float, second: float, ..., fifth: float, rest: array<float>}
// But doing so would take too much time, so I'll leave it as an assertion
E.A.R.firstErrorOrOpen(samples)->E.R2.fmap(x =>
E.R.toExnFnString(Error.sampleSetErrorToString, make(x))
)
}
let mean = t => T.get(t)->E.A.Floats.mean let mean = t => T.get(t)->E.A.Floats.mean
let geomean = t => T.get(t)->E.A.Floats.geomean let geomean = t => T.get(t)->E.A.Floats.geomean

View File

@ -75,7 +75,7 @@ module Process = {
| Ok((t1, t2)) => | Ok((t1, t2)) =>
switch SampleSetDist.map2(~fn=altFn, ~t1, ~t2) { switch SampleSetDist.map2(~fn=altFn, ~t1, ~t2) {
| Ok(r) => Ok(DistributionTypes.SampleSet(r)) | Ok(r) => Ok(DistributionTypes.SampleSet(r))
| Error(r) => Error(Operation.Error.toString(r)) | Error(r) => Error(SampleSetDist.Error.toString(r))
} }
| Error(r) => Error(DistributionTypes.Error.toString(r)) | Error(r) => Error(DistributionTypes.Error.toString(r))
} }

View File

@ -122,12 +122,12 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce
let map2 = (t1: t, t2: t, aLambdaValue) => { let map2 = (t1: t, t2: t, aLambdaValue) => {
let fn = (a, b) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b)}) let fn = (a, b) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b)})
SampleSetDist.map2(~fn, ~t1, ~t2)->E.R2.errMap(SampleSetDist.Error.fromOperationError)->toType SampleSetDist.map2(~fn, ~t1, ~t2)->toType
} }
let map3 = (t1: t, t2: t, t3: t, aLambdaValue) => { let map3 = (t1: t, t2: t, t3: t, aLambdaValue) => {
let fn = (a, b, c) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b), EvNumber(c)}) let fn = (a, b, c) => doLambdaCall(aLambdaValue, list{EvNumber(a), EvNumber(b), EvNumber(c)})
SampleSetDist.map3(~fn, ~t1, ~t2, ~t3)->E.R2.errMap(SampleSetDist.Error.fromOperationError)->toType SampleSetDist.map3(~fn, ~t1, ~t2, ~t3)->toType
} }
} }

View File

@ -55,6 +55,10 @@ module Tuple2 = {
let toFnCall = (fn, (a1, a2)) => fn(a1, a2) let toFnCall = (fn, (a1, a2)) => fn(a1, a2)
} }
module Tuple3 = {
let toFnCall = (fn, (a1, a2, a3)) => fn(a1, a2, a3)
}
module O = { module O = {
let dimap = (sFn, rFn, e) => let dimap = (sFn, rFn, e) =>
switch e { switch e {