Simple module-functor work
This commit is contained in:
		
							parent
							
								
									da172bfa94
								
							
						
					
					
						commit
						0d2c53eca4
					
				| 
						 | 
				
			
			@ -14,38 +14,15 @@ let max = (f1: option(float), f2: option(float)) =>
 | 
			
		|||
  | (None, None) => None
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
type mixedPoint = {
 | 
			
		||||
  continuous: float,
 | 
			
		||||
  discrete: float,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module MixedPoint = {
 | 
			
		||||
  type t = mixedPoint;
 | 
			
		||||
  let toContinuousValue = (t: t) => t.continuous;
 | 
			
		||||
  let toDiscreteValue = (t: t) => t.discrete;
 | 
			
		||||
  let makeContinuous = (continuous: float): t => {continuous, discrete: 0.0};
 | 
			
		||||
  let makeDiscrete = (discrete: float): t => {continuous: 0.0, discrete};
 | 
			
		||||
 | 
			
		||||
  let fmap = (fn, t: t) => {
 | 
			
		||||
    continuous: fn(t.continuous),
 | 
			
		||||
    discrete: fn(t.discrete),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let combine2 = (fn, c: t, d: t): t => {
 | 
			
		||||
    continuous: fn(c.continuous, d.continuous),
 | 
			
		||||
    discrete: fn(c.discrete, d.discrete),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let add = combine2((a, b) => a +. b);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module type dist = {
 | 
			
		||||
  type t;
 | 
			
		||||
  let minX: t => option(float);
 | 
			
		||||
  let maxX: t => option(float);
 | 
			
		||||
  let pointwiseFmap: (float => float, t) => t;
 | 
			
		||||
  let xToY: (float, t) => mixedPoint;
 | 
			
		||||
  let shape: t => DistributionTypes.shape;
 | 
			
		||||
  let xToY: (float, t) => DistributionTypes.mixedPoint;
 | 
			
		||||
  let toShape: t => DistributionTypes.shape;
 | 
			
		||||
  let toContinuous: t => option(DistributionTypes.continuousShape);
 | 
			
		||||
  let toDiscrete: t => option(DistributionTypes.discreteShape);
 | 
			
		||||
 | 
			
		||||
  type integral;
 | 
			
		||||
  let integral: (~cache: option(integral), t) => integral;
 | 
			
		||||
| 
						 | 
				
			
			@ -60,7 +37,11 @@ module Dist = (T: dist) => {
 | 
			
		|||
  let maxX = T.maxX;
 | 
			
		||||
  let pointwiseFmap = T.pointwiseFmap;
 | 
			
		||||
  let xToY = T.xToY;
 | 
			
		||||
  let shape = T.shape;
 | 
			
		||||
  let toShape = T.toShape;
 | 
			
		||||
  let toContinuous = T.toContinuous;
 | 
			
		||||
  let toDiscrete = T.toDiscrete;
 | 
			
		||||
  let scaleBy = (~scale=1.0, t: t) =>
 | 
			
		||||
    t |> pointwiseFmap((r: float) => r *. scale);
 | 
			
		||||
 | 
			
		||||
  module Integral = {
 | 
			
		||||
    type t = T.integral;
 | 
			
		||||
| 
						 | 
				
			
			@ -70,228 +51,285 @@ module Dist = (T: dist) => {
 | 
			
		|||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module Continuous =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.continuousShape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
    let make = (shape, interpolation): t => {shape, interpolation};
 | 
			
		||||
    let fromShape = shape => make(shape, `Linear);
 | 
			
		||||
    let shape = (t: t) => t.shape;
 | 
			
		||||
    let shapeFn = (fn, t: t) => t |> shape |> fn;
 | 
			
		||||
    let shape = (t: t) => t.shape;
 | 
			
		||||
    let integral = (~cache, t) =>
 | 
			
		||||
      cache
 | 
			
		||||
      |> E.O.default(
 | 
			
		||||
           t
 | 
			
		||||
           |> shape
 | 
			
		||||
           |> XYShape.Range.integrateWithTriangles
 | 
			
		||||
           |> E.O.toExt("")
 | 
			
		||||
           |> fromShape,
 | 
			
		||||
         );
 | 
			
		||||
    //   This seems wrong, we really want the ending bit, I'd assume
 | 
			
		||||
    let integralSum = (~cache, t) =>
 | 
			
		||||
      t |> integral(~cache) |> shape |> XYShape.ySum;
 | 
			
		||||
    let minX = shapeFn(XYShape.minX);
 | 
			
		||||
    let maxX = shapeFn(XYShape.maxX);
 | 
			
		||||
    let pointwiseFmap = (fn, t: t) =>
 | 
			
		||||
      t |> shape |> XYShape.pointwiseMap(fn) |> fromShape;
 | 
			
		||||
    let shape = (t: t): DistributionTypes.shape => Continuous(t);
 | 
			
		||||
    let xToY = (f, t) =>
 | 
			
		||||
      shapeFn(CdfLibrary.Distribution.findY(f), t)
 | 
			
		||||
      |> MixedPoint.makeContinuous;
 | 
			
		||||
    let integralXtoY = (~cache, f, t) =>
 | 
			
		||||
      t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f));
 | 
			
		||||
  });
 | 
			
		||||
module Continuous = {
 | 
			
		||||
  type t = DistributionTypes.continuousShape;
 | 
			
		||||
  let xyShape = (t: t) => t.xyShape;
 | 
			
		||||
  let getShape = (t: t) => t.xyShape;
 | 
			
		||||
  let interpolation = (t: t) => t.interpolation;
 | 
			
		||||
  let make = (xyShape, interpolation): t => {xyShape, interpolation};
 | 
			
		||||
  let fromShape = xyShape => make(xyShape, `Linear);
 | 
			
		||||
  let shapeMap = (fn, {xyShape, interpolation}: t): t => {
 | 
			
		||||
    xyShape: fn(xyShape),
 | 
			
		||||
    interpolation,
 | 
			
		||||
  };
 | 
			
		||||
  let oShapeMap =
 | 
			
		||||
      (fn, {xyShape, interpolation}: t)
 | 
			
		||||
      : option(DistributionTypes.continuousShape) =>
 | 
			
		||||
    fn(xyShape) |> E.O.fmap(xyShape => make(xyShape, interpolation));
 | 
			
		||||
 | 
			
		||||
module Discrete =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.discreteShape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
    let integral = (~cache, t) =>
 | 
			
		||||
      cache
 | 
			
		||||
      |> E.O.default(t |> XYShape.accumulateYs |> Shape.Continuous.fromShape);
 | 
			
		||||
    let integralSum = (~cache, t) => t |> XYShape.ySum;
 | 
			
		||||
    let minX = XYShape.minX;
 | 
			
		||||
    let maxX = XYShape.maxX;
 | 
			
		||||
    let pointwiseFmap = XYShape.pointwiseMap;
 | 
			
		||||
    let shape = (t: t): DistributionTypes.shape => Discrete(t);
 | 
			
		||||
    let xToY = (f, t) =>
 | 
			
		||||
      CdfLibrary.Distribution.findY(f, t) |> MixedPoint.makeDiscrete;
 | 
			
		||||
    let integralXtoY = (~cache, f, t) =>
 | 
			
		||||
      t |> XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f);
 | 
			
		||||
  });
 | 
			
		||||
  module T =
 | 
			
		||||
    Dist({
 | 
			
		||||
      type t = DistributionTypes.continuousShape;
 | 
			
		||||
      type integral = DistributionTypes.continuousShape;
 | 
			
		||||
      let shapeFn = (fn, t: t) => t |> xyShape |> fn;
 | 
			
		||||
      let integral = (~cache, t) =>
 | 
			
		||||
        cache
 | 
			
		||||
        |> E.O.default(
 | 
			
		||||
             t
 | 
			
		||||
             |> xyShape
 | 
			
		||||
             |> XYShape.Range.integrateWithTriangles
 | 
			
		||||
             |> E.O.toExt("")
 | 
			
		||||
             |> fromShape,
 | 
			
		||||
           );
 | 
			
		||||
      //   This seems wrong, we really want the ending bit, I'd assume
 | 
			
		||||
      let integralSum = (~cache, t) =>
 | 
			
		||||
        t |> integral(~cache) |> xyShape |> XYShape.ySum;
 | 
			
		||||
      let minX = shapeFn(XYShape.minX);
 | 
			
		||||
      let maxX = shapeFn(XYShape.maxX);
 | 
			
		||||
      let pointwiseFmap = (fn, t: t) =>
 | 
			
		||||
        t |> xyShape |> XYShape.pointwiseMap(fn) |> fromShape;
 | 
			
		||||
      let toShape = (t: t): DistributionTypes.shape => Continuous(t);
 | 
			
		||||
      let xToY = (f, t) =>
 | 
			
		||||
        shapeFn(CdfLibrary.Distribution.findY(f), t)
 | 
			
		||||
        |> DistributionTypes.MixedPoint.makeContinuous;
 | 
			
		||||
      let integralXtoY = (~cache, f, t) =>
 | 
			
		||||
        t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f));
 | 
			
		||||
      let toContinuous = t => Some(t);
 | 
			
		||||
      let toDiscrete = _ => None;
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module Mixed =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.mixedShape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
    let minX = ({continuous, discrete}: t) =>
 | 
			
		||||
      min(Continuous.minX(continuous), Discrete.minX(discrete));
 | 
			
		||||
    let maxX = ({continuous, discrete}: t) =>
 | 
			
		||||
      max(Continuous.maxX(continuous), Discrete.maxX(discrete));
 | 
			
		||||
    let shape = (t: t): DistributionTypes.shape => Mixed(t);
 | 
			
		||||
    let xToY =
 | 
			
		||||
        (f, {discrete, continuous, discreteProbabilityMassFraction}: t) => {
 | 
			
		||||
      let c =
 | 
			
		||||
        continuous
 | 
			
		||||
        |> Continuous.xToY(f)
 | 
			
		||||
        |> MixedPoint.fmap(e => e *. (1. -. discreteProbabilityMassFraction));
 | 
			
		||||
      let d =
 | 
			
		||||
module Discrete = {
 | 
			
		||||
  module T =
 | 
			
		||||
    Dist({
 | 
			
		||||
      type t = DistributionTypes.discreteShape;
 | 
			
		||||
      type integral = DistributionTypes.continuousShape;
 | 
			
		||||
      let integral = (~cache, t) =>
 | 
			
		||||
        cache
 | 
			
		||||
        |> E.O.default(t |> XYShape.accumulateYs |> Continuous.fromShape);
 | 
			
		||||
      let integralSum = (~cache, t) => t |> XYShape.ySum;
 | 
			
		||||
      let minX = XYShape.minX;
 | 
			
		||||
      let maxX = XYShape.maxX;
 | 
			
		||||
      let pointwiseFmap = XYShape.pointwiseMap;
 | 
			
		||||
      let toShape = (t: t): DistributionTypes.shape => Discrete(t);
 | 
			
		||||
      let toContinuous = _ => None;
 | 
			
		||||
      let toDiscrete = t => Some(t);
 | 
			
		||||
      let xToY = (f, t) =>
 | 
			
		||||
        CdfLibrary.Distribution.findY(f, t)
 | 
			
		||||
        |> DistributionTypes.MixedPoint.makeDiscrete;
 | 
			
		||||
      let integralXtoY = (~cache, f, t) =>
 | 
			
		||||
        t |> XYShape.accumulateYs |> CdfLibrary.Distribution.findY(f);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module Mixed = {
 | 
			
		||||
  module T =
 | 
			
		||||
    Dist({
 | 
			
		||||
      type t = DistributionTypes.mixedShape;
 | 
			
		||||
      type integral = DistributionTypes.continuousShape;
 | 
			
		||||
      let minX = ({continuous, discrete}: t) =>
 | 
			
		||||
        min(Continuous.T.minX(continuous), Discrete.T.minX(discrete));
 | 
			
		||||
      let maxX = ({continuous, discrete}: t) =>
 | 
			
		||||
        max(Continuous.T.maxX(continuous), Discrete.T.maxX(discrete));
 | 
			
		||||
      let toShape = (t: t): DistributionTypes.shape => Mixed(t);
 | 
			
		||||
      let toContinuous = ({continuous}: t) => Some(continuous);
 | 
			
		||||
      let toDiscrete = ({discrete}: t) => Some(discrete);
 | 
			
		||||
      let xToY =
 | 
			
		||||
          (f, {discrete, continuous, discreteProbabilityMassFraction}: t) => {
 | 
			
		||||
        let c =
 | 
			
		||||
          continuous
 | 
			
		||||
          |> Continuous.T.xToY(f)
 | 
			
		||||
          |> DistributionTypes.MixedPoint.fmap(e =>
 | 
			
		||||
               e *. (1. -. discreteProbabilityMassFraction)
 | 
			
		||||
             );
 | 
			
		||||
        let d =
 | 
			
		||||
          discrete
 | 
			
		||||
          |> Discrete.T.xToY(f)
 | 
			
		||||
          |> DistributionTypes.MixedPoint.fmap(e =>
 | 
			
		||||
               e *. discreteProbabilityMassFraction
 | 
			
		||||
             );
 | 
			
		||||
        DistributionTypes.MixedPoint.add(c, d);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      // todo: FixMe
 | 
			
		||||
      let scaledContinuousComponent =
 | 
			
		||||
          ({continuous, discreteProbabilityMassFraction}: t)
 | 
			
		||||
          : option(DistributionTypes.continuousShape) =>
 | 
			
		||||
        Some(continuous);
 | 
			
		||||
 | 
			
		||||
      let scaledDiscreteComponent =
 | 
			
		||||
          ({discrete, discreteProbabilityMassFraction}: t)
 | 
			
		||||
          : DistributionTypes.continuousShape =>
 | 
			
		||||
        Continuous.make(
 | 
			
		||||
          Discrete.T.pointwiseFmap(
 | 
			
		||||
            f => f *. discreteProbabilityMassFraction,
 | 
			
		||||
            discrete,
 | 
			
		||||
          ),
 | 
			
		||||
          `Stepwise,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
      // TODO: Add these two directly, once interpolation is added.
 | 
			
		||||
      let integral = (~cache, t) => {
 | 
			
		||||
        //   let cont = scaledContinuousComponent(t);
 | 
			
		||||
        //   let discrete = scaledDiscreteComponent(t);
 | 
			
		||||
        switch (cache) {
 | 
			
		||||
        | Some(cache) => cache
 | 
			
		||||
        | None => scaledContinuousComponent(t) |> E.O.toExt("")
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      let integralSum =
 | 
			
		||||
          (
 | 
			
		||||
            ~cache,
 | 
			
		||||
            {discrete, continuous, discreteProbabilityMassFraction}: t,
 | 
			
		||||
          ) => {
 | 
			
		||||
        switch (cache) {
 | 
			
		||||
        | Some(cache) => 3.0
 | 
			
		||||
        | None =>
 | 
			
		||||
          Discrete.T.Integral.sum(~cache=None, discrete)
 | 
			
		||||
          *. discreteProbabilityMassFraction
 | 
			
		||||
          +. Continuous.T.Integral.sum(~cache=None, continuous)
 | 
			
		||||
          *. (1.0 -. discreteProbabilityMassFraction)
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      let integralXtoY =
 | 
			
		||||
          (
 | 
			
		||||
            ~cache,
 | 
			
		||||
            f,
 | 
			
		||||
            {discrete, continuous, discreteProbabilityMassFraction}: t,
 | 
			
		||||
          ) => {
 | 
			
		||||
        let cont = Continuous.T.Integral.xToY(~cache, f, continuous);
 | 
			
		||||
        let discrete = Discrete.T.Integral.xToY(~cache, f, discrete);
 | 
			
		||||
        discrete
 | 
			
		||||
        |> Discrete.xToY(f)
 | 
			
		||||
        |> MixedPoint.fmap(e => e *. discreteProbabilityMassFraction);
 | 
			
		||||
      MixedPoint.add(c, d);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let scaledContinuousComponent =
 | 
			
		||||
        ({continuous, discreteProbabilityMassFraction}: t)
 | 
			
		||||
        : option(DistributionTypes.continuousShape) => {
 | 
			
		||||
      Shape.Continuous.scalePdf(
 | 
			
		||||
        ~scaleTo=1.0 -. discreteProbabilityMassFraction,
 | 
			
		||||
        continuous,
 | 
			
		||||
      );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let scaledDiscreteComponent =
 | 
			
		||||
        ({discrete, discreteProbabilityMassFraction}: t)
 | 
			
		||||
        : DistributionTypes.continuousShape =>
 | 
			
		||||
      Shape.Continuous.make(
 | 
			
		||||
        Discrete.pointwiseFmap(
 | 
			
		||||
          f => f *. discreteProbabilityMassFraction,
 | 
			
		||||
          discrete,
 | 
			
		||||
        ),
 | 
			
		||||
        `Stepwise,
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
    // TODO: Add these two directly, once interpolation is added.
 | 
			
		||||
    let integral = (~cache, t) => {
 | 
			
		||||
      //   let cont = scaledContinuousComponent(t);
 | 
			
		||||
      //   let discrete = scaledDiscreteComponent(t);
 | 
			
		||||
      switch (cache) {
 | 
			
		||||
      | Some(cache) => cache
 | 
			
		||||
      | None => scaledContinuousComponent(t) |> E.O.toExt("")
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let integralSum =
 | 
			
		||||
        (~cache, {discrete, continuous, discreteProbabilityMassFraction}: t) => {
 | 
			
		||||
      switch (cache) {
 | 
			
		||||
      | Some(cache) => 3.0
 | 
			
		||||
      | None =>
 | 
			
		||||
        Discrete.Integral.sum(~cache=None, discrete)
 | 
			
		||||
        *. discreteProbabilityMassFraction
 | 
			
		||||
        +. Continuous.Integral.sum(~cache=None, continuous)
 | 
			
		||||
        *. (1.0 -. discreteProbabilityMassFraction)
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let integralXtoY =
 | 
			
		||||
        (
 | 
			
		||||
          ~cache,
 | 
			
		||||
          f,
 | 
			
		||||
          {discrete, continuous, discreteProbabilityMassFraction}: t,
 | 
			
		||||
        ) => {
 | 
			
		||||
      let cont = Continuous.Integral.xToY(~cache, f, continuous);
 | 
			
		||||
      let discrete = Discrete.Integral.xToY(~cache, f, discrete);
 | 
			
		||||
      discrete
 | 
			
		||||
      *. discreteProbabilityMassFraction
 | 
			
		||||
      +. cont
 | 
			
		||||
      *. (1.0 -. discreteProbabilityMassFraction);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let pointwiseFmap =
 | 
			
		||||
        (fn, {discrete, continuous, discreteProbabilityMassFraction}: t): t => {
 | 
			
		||||
      {
 | 
			
		||||
        discrete: Discrete.pointwiseFmap(fn, discrete),
 | 
			
		||||
        continuous: Continuous.pointwiseFmap(fn, continuous),
 | 
			
		||||
        discreteProbabilityMassFraction,
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
module Shape =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.shape;
 | 
			
		||||
    type integral = DistributionTypes.continuousShape;
 | 
			
		||||
 | 
			
		||||
    let mapToAll = (t: t, (fn1, fn2, fn3)) =>
 | 
			
		||||
      switch (t) {
 | 
			
		||||
      | Mixed(m) => fn1(m)
 | 
			
		||||
      | Discrete(m) => fn2(m)
 | 
			
		||||
      | Continuous(m) => fn3(m)
 | 
			
		||||
        +. cont
 | 
			
		||||
        *. (1.0 -. discreteProbabilityMassFraction);
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
    let fmap = (t: t, (fn1, fn2, fn3)): t =>
 | 
			
		||||
      switch (t) {
 | 
			
		||||
      | Mixed(m) => Mixed(fn1(m))
 | 
			
		||||
      | Discrete(m) => Discrete(fn2(m))
 | 
			
		||||
      | Continuous(m) => Continuous(fn3(m))
 | 
			
		||||
      let pointwiseFmap =
 | 
			
		||||
          (fn, {discrete, continuous, discreteProbabilityMassFraction}: t): t => {
 | 
			
		||||
        {
 | 
			
		||||
          discrete: Discrete.T.pointwiseFmap(fn, discrete),
 | 
			
		||||
          continuous: Continuous.T.pointwiseFmap(fn, continuous),
 | 
			
		||||
          discreteProbabilityMassFraction,
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    let xToY = (f, t) =>
 | 
			
		||||
      mapToAll(t, (Mixed.xToY(f), Discrete.xToY(f), Continuous.xToY(f)));
 | 
			
		||||
    let shape = (t: t) => t;
 | 
			
		||||
    let minX = (t: t) =>
 | 
			
		||||
      mapToAll(t, (Mixed.minX, Discrete.minX, Continuous.minX));
 | 
			
		||||
    let integral = (~cache, t: t) =>
 | 
			
		||||
      mapToAll(
 | 
			
		||||
        t,
 | 
			
		||||
        (
 | 
			
		||||
          Mixed.Integral.get(~cache),
 | 
			
		||||
          Discrete.Integral.get(~cache),
 | 
			
		||||
          Continuous.Integral.get(~cache),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
    let integralSum = (~cache, t: t) =>
 | 
			
		||||
      mapToAll(
 | 
			
		||||
        t,
 | 
			
		||||
        (
 | 
			
		||||
          Mixed.Integral.sum(~cache),
 | 
			
		||||
          Discrete.Integral.sum(~cache),
 | 
			
		||||
          Continuous.Integral.sum(~cache),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
    let integralXtoY = (~cache, f, t) => {
 | 
			
		||||
      mapToAll(
 | 
			
		||||
        t,
 | 
			
		||||
        (
 | 
			
		||||
          Mixed.Integral.xToY(~cache, f),
 | 
			
		||||
          Discrete.Integral.xToY(~cache, f),
 | 
			
		||||
          Continuous.Integral.xToY(~cache, f),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
    };
 | 
			
		||||
    let maxX = (t: t) =>
 | 
			
		||||
      mapToAll(t, (Mixed.minX, Discrete.minX, Continuous.minX));
 | 
			
		||||
    let pointwiseFmap = (fn, t: t) =>
 | 
			
		||||
      fmap(
 | 
			
		||||
        t,
 | 
			
		||||
        (
 | 
			
		||||
          Mixed.pointwiseFmap(fn),
 | 
			
		||||
          Discrete.pointwiseFmap(fn),
 | 
			
		||||
          Continuous.pointwiseFmap(fn),
 | 
			
		||||
        ),
 | 
			
		||||
      );
 | 
			
		||||
  });
 | 
			
		||||
module Shape = {
 | 
			
		||||
  module T =
 | 
			
		||||
    Dist({
 | 
			
		||||
      type t = DistributionTypes.shape;
 | 
			
		||||
      type integral = DistributionTypes.continuousShape;
 | 
			
		||||
 | 
			
		||||
module WithMetadata =
 | 
			
		||||
  Dist({
 | 
			
		||||
    type t = DistributionTypes.complexPower;
 | 
			
		||||
    type integral = DistributionTypes.complexPower;
 | 
			
		||||
    let shape = ({shape, _}: t) => shape;
 | 
			
		||||
    let xToY = (f, t: t) => t |> shape |> Shape.xToY(f);
 | 
			
		||||
    let minX = (t: t) => t |> shape |> Shape.minX;
 | 
			
		||||
    let maxX = (t: t) => t |> shape |> Shape.maxX;
 | 
			
		||||
    let fromShape = (shape, t): t => DistributionTypes.update(~shape, t);
 | 
			
		||||
    let pointwiseFmap = (fn, {shape, _} as t: t): t =>
 | 
			
		||||
      fromShape(Shape.pointwiseFmap(fn, shape), t);
 | 
			
		||||
      let mapToAll = (t: t, (fn1, fn2, fn3)) =>
 | 
			
		||||
        switch (t) {
 | 
			
		||||
        | Mixed(m) => fn1(m)
 | 
			
		||||
        | Discrete(m) => fn2(m)
 | 
			
		||||
        | Continuous(m) => fn3(m)
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    let integral = (~cache as _, t: t) =>
 | 
			
		||||
      fromShape(Continuous(t.integralCache), t);
 | 
			
		||||
    let integralSum = (~cache as _, t: t) =>
 | 
			
		||||
      t |> shape |> Shape.Integral.sum(~cache=Some(t.integralCache));
 | 
			
		||||
    //   TODO: Fix this below, obviously.
 | 
			
		||||
    let integralXtoY = (~cache as _, f, t) => {
 | 
			
		||||
      1337.0;
 | 
			
		||||
    };
 | 
			
		||||
  });
 | 
			
		||||
      let fmap = (t: t, (fn1, fn2, fn3)): t =>
 | 
			
		||||
        switch (t) {
 | 
			
		||||
        | Mixed(m) => Mixed(fn1(m))
 | 
			
		||||
        | Discrete(m) => Discrete(fn2(m))
 | 
			
		||||
        | Continuous(m) => Continuous(fn3(m))
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
      let xToY = (f, t) =>
 | 
			
		||||
        mapToAll(
 | 
			
		||||
          t,
 | 
			
		||||
          (Mixed.T.xToY(f), Discrete.T.xToY(f), Continuous.T.xToY(f)),
 | 
			
		||||
        );
 | 
			
		||||
      let toShape = (t: t) => t;
 | 
			
		||||
      let toContinuous = (t: t) =>
 | 
			
		||||
        mapToAll(
 | 
			
		||||
          t,
 | 
			
		||||
          (
 | 
			
		||||
            Mixed.T.toContinuous,
 | 
			
		||||
            Discrete.T.toContinuous,
 | 
			
		||||
            Continuous.T.toContinuous,
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      let toDiscrete = (t: t) =>
 | 
			
		||||
        mapToAll(
 | 
			
		||||
          t,
 | 
			
		||||
          (
 | 
			
		||||
            Mixed.T.toDiscrete,
 | 
			
		||||
            Discrete.T.toDiscrete,
 | 
			
		||||
            Continuous.T.toDiscrete,
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      let minX = (t: t) =>
 | 
			
		||||
        mapToAll(t, (Mixed.T.minX, Discrete.T.minX, Continuous.T.minX));
 | 
			
		||||
      let integral = (~cache, t: t) =>
 | 
			
		||||
        mapToAll(
 | 
			
		||||
          t,
 | 
			
		||||
          (
 | 
			
		||||
            Mixed.T.Integral.get(~cache),
 | 
			
		||||
            Discrete.T.Integral.get(~cache),
 | 
			
		||||
            Continuous.T.Integral.get(~cache),
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      let integralSum = (~cache, t: t) =>
 | 
			
		||||
        mapToAll(
 | 
			
		||||
          t,
 | 
			
		||||
          (
 | 
			
		||||
            Mixed.T.Integral.sum(~cache),
 | 
			
		||||
            Discrete.T.Integral.sum(~cache),
 | 
			
		||||
            Continuous.T.Integral.sum(~cache),
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      let integralXtoY = (~cache, f, t) => {
 | 
			
		||||
        mapToAll(
 | 
			
		||||
          t,
 | 
			
		||||
          (
 | 
			
		||||
            Mixed.T.Integral.xToY(~cache, f),
 | 
			
		||||
            Discrete.T.Integral.xToY(~cache, f),
 | 
			
		||||
            Continuous.T.Integral.xToY(~cache, f),
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
      };
 | 
			
		||||
      let maxX = (t: t) =>
 | 
			
		||||
        mapToAll(t, (Mixed.T.minX, Discrete.T.minX, Continuous.T.minX));
 | 
			
		||||
      let pointwiseFmap = (fn, t: t) =>
 | 
			
		||||
        fmap(
 | 
			
		||||
          t,
 | 
			
		||||
          (
 | 
			
		||||
            Mixed.T.pointwiseFmap(fn),
 | 
			
		||||
            Discrete.T.pointwiseFmap(fn),
 | 
			
		||||
            Continuous.T.pointwiseFmap(fn),
 | 
			
		||||
          ),
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module WithMetadata = {
 | 
			
		||||
  module T =
 | 
			
		||||
    Dist({
 | 
			
		||||
      type t = DistributionTypes.complexPower;
 | 
			
		||||
      type integral = DistributionTypes.complexPower;
 | 
			
		||||
      let toShape = ({shape, _}: t) => shape;
 | 
			
		||||
      let toContinuous = (t: t) => t |> toShape |> Shape.T.toContinuous;
 | 
			
		||||
      let toDiscrete = (t: t) => t |> toShape |> Shape.T.toDiscrete;
 | 
			
		||||
      // todo: adjust for limit, and the fact that total mass is lower.
 | 
			
		||||
      let xToY = (f, t: t) => t |> toShape |> Shape.T.xToY(f);
 | 
			
		||||
      let minX = (t: t) => t |> toShape |> Shape.T.minX;
 | 
			
		||||
      let maxX = (t: t) => t |> toShape |> Shape.T.maxX;
 | 
			
		||||
      let fromShape = (shape, t): t => DistributionTypes.update(~shape, t);
 | 
			
		||||
      // todo: adjust for limit
 | 
			
		||||
      let pointwiseFmap = (fn, {shape, _} as t: t): t =>
 | 
			
		||||
        fromShape(Shape.T.pointwiseFmap(fn, shape), t);
 | 
			
		||||
 | 
			
		||||
      let integral = (~cache as _, t: t) =>
 | 
			
		||||
        fromShape(Continuous(t.integralCache), t);
 | 
			
		||||
      let integralSum = (~cache as _, t: t) =>
 | 
			
		||||
        t |> toShape |> Shape.T.Integral.sum(~cache=Some(t.integralCache));
 | 
			
		||||
      //   TODO: Fix this below, obviously. Adjust for limit.
 | 
			
		||||
      let integralXtoY = (~cache as _, f, t) => {
 | 
			
		||||
        1337.0;
 | 
			
		||||
      };
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -17,21 +17,10 @@ type xyShape = {
 | 
			
		|||
type interpolationMethod = [ | `Stepwise | `Linear];
 | 
			
		||||
 | 
			
		||||
type continuousShape = {
 | 
			
		||||
  shape: xyShape,
 | 
			
		||||
  xyShape,
 | 
			
		||||
  interpolation: interpolationMethod,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module ContinuousShape = {
 | 
			
		||||
  type t = continuousShape;
 | 
			
		||||
  let shape = (t: t) => t.shape;
 | 
			
		||||
  let interpolation = (t: t) => t.interpolation;
 | 
			
		||||
  let make = (shape, interpolation) => {shape, interpolation};
 | 
			
		||||
  let shapeMap = ({shape, interpolation}: t, fn) => {
 | 
			
		||||
    shape: fn(shape),
 | 
			
		||||
    interpolation,
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type discreteShape = xyShape;
 | 
			
		||||
 | 
			
		||||
type mixedShape = {
 | 
			
		||||
| 
						 | 
				
			
			@ -111,4 +100,29 @@ module DistributionUnit = {
 | 
			
		|||
      )
 | 
			
		||||
    | _ => Js.Null.fromOption(None)
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type mixedPoint = {
 | 
			
		||||
  continuous: float,
 | 
			
		||||
  discrete: float,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module MixedPoint = {
 | 
			
		||||
  type t = mixedPoint;
 | 
			
		||||
  let toContinuousValue = (t: t) => t.continuous;
 | 
			
		||||
  let toDiscreteValue = (t: t) => t.discrete;
 | 
			
		||||
  let makeContinuous = (continuous: float): t => {continuous, discrete: 0.0};
 | 
			
		||||
  let makeDiscrete = (discrete: float): t => {continuous: 0.0, discrete};
 | 
			
		||||
 | 
			
		||||
  let fmap = (fn, t: t) => {
 | 
			
		||||
    continuous: fn(t.continuous),
 | 
			
		||||
    discrete: fn(t.discrete),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let combine2 = (fn, c: t, d: t): t => {
 | 
			
		||||
    continuous: fn(c.continuous, d.continuous),
 | 
			
		||||
    discrete: fn(c.discrete, d.discrete),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  let add = combine2((a, b) => a +. b);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -6,18 +6,20 @@ type pointInRange =
 | 
			
		|||
 | 
			
		||||
module Continuous = {
 | 
			
		||||
  type t = continuousShape;
 | 
			
		||||
  let shape = (t: t) => t.shape;
 | 
			
		||||
  let getShape = (t: t) => t.shape;
 | 
			
		||||
  let xyShape = (t: t) => t.xyShape;
 | 
			
		||||
  let getShape = (t: t) => t.xyShape;
 | 
			
		||||
  let interpolation = (t: t) => t.interpolation;
 | 
			
		||||
  let make = (shape, interpolation) => {shape, interpolation};
 | 
			
		||||
  let fromShape = shape => make(shape, `Linear);
 | 
			
		||||
  let shapeMap = (fn, {shape, interpolation}: t) => {
 | 
			
		||||
    shape: fn(shape),
 | 
			
		||||
  let make = (xyShape, interpolation): t => {xyShape, interpolation};
 | 
			
		||||
  let fromShape = xyShape => make(xyShape, `Linear);
 | 
			
		||||
  let shapeMap = (fn, {xyShape, interpolation}: t): t => {
 | 
			
		||||
    xyShape: fn(xyShape),
 | 
			
		||||
    interpolation,
 | 
			
		||||
  };
 | 
			
		||||
  let oShapeMap = (fn, {shape, interpolation}: t) =>
 | 
			
		||||
    fn(shape) |> E.O.fmap(shape => {shape, interpolation});
 | 
			
		||||
  let shapeFn = (fn, t: t) => t |> shape |> fn;
 | 
			
		||||
  let oShapeMap =
 | 
			
		||||
      (fn, {xyShape, interpolation}: t)
 | 
			
		||||
      : option(DistributionTypes.continuousShape) =>
 | 
			
		||||
    fn(xyShape) |> E.O.fmap(xyShape => make(xyShape, interpolation));
 | 
			
		||||
  let shapeFn = (fn, t: t) => t |> xyShape |> fn;
 | 
			
		||||
  let minX = shapeFn(XYShape.minX);
 | 
			
		||||
  let maxX = shapeFn(XYShape.maxX);
 | 
			
		||||
  let findX = y => shapeFn(CdfLibrary.Distribution.findX(y));
 | 
			
		||||
| 
						 | 
				
			
			@ -29,15 +31,18 @@ module Continuous = {
 | 
			
		|||
  let findIntegralY = (f, t) => {
 | 
			
		||||
    t
 | 
			
		||||
    |> toCdf
 | 
			
		||||
    |> E.O.fmap(shape)
 | 
			
		||||
    |> E.O.fmap(xyShape)
 | 
			
		||||
    |> E.O.fmap(CdfLibrary.Distribution.findY(f));
 | 
			
		||||
  };
 | 
			
		||||
  let normalizeCdf = (continuousShape: continuousShape) =>
 | 
			
		||||
    continuousShape |> shape |> XYShape.scaleCdfTo(~scaleTo=1.0) |> fromShape;
 | 
			
		||||
    continuousShape
 | 
			
		||||
    |> xyShape
 | 
			
		||||
    |> XYShape.scaleCdfTo(~scaleTo=1.0)
 | 
			
		||||
    |> fromShape;
 | 
			
		||||
  let scalePdf = (~scaleTo=1.0, continuousShape: continuousShape) => {
 | 
			
		||||
    switch (toCdf(continuousShape)) {
 | 
			
		||||
    | Some({shape}) =>
 | 
			
		||||
      XYShape.scaleCdfTo(~scaleTo, shape)
 | 
			
		||||
    | Some({xyShape}) =>
 | 
			
		||||
      XYShape.scaleCdfTo(~scaleTo, xyShape)
 | 
			
		||||
      |> XYShape.Range.derivative
 | 
			
		||||
      |> E.O.fmap(fromShape)
 | 
			
		||||
    | _ => None
 | 
			
		||||
| 
						 | 
				
			
			@ -162,14 +167,14 @@ module Mixed = {
 | 
			
		|||
  let clean = (t: DistributionTypes.mixedShape) =>
 | 
			
		||||
    switch (t) {
 | 
			
		||||
    | {
 | 
			
		||||
        continuous: {shape: {xs: [||], ys: [||]}},
 | 
			
		||||
        continuous: {xyShape: {xs: [||], ys: [||]}},
 | 
			
		||||
        discrete: {xs: [||], ys: [||]},
 | 
			
		||||
      } =>
 | 
			
		||||
      None
 | 
			
		||||
    | {discrete: {xs: [|_|], ys: [|_|]}} => None
 | 
			
		||||
    | {continuous, discrete: {xs: [||], ys: [||]}} =>
 | 
			
		||||
      Some(Continuous(continuous))
 | 
			
		||||
    | {continuous: {shape: {xs: [||], ys: [||]}}, discrete} =>
 | 
			
		||||
    | {continuous: {xyShape: {xs: [||], ys: [||]}}, discrete} =>
 | 
			
		||||
      Some(Discrete(discrete))
 | 
			
		||||
    | shape => Some(Mixed(shape))
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user