open System
open LanguagePrimitives
module RoundedCalculation =
[<Measure>]
type rounded
type NotRounded = float
type Rounded = float<rounded>
let mutable _sigDigs = 0
let inline round x = Math.Round(float x, _sigDigs) |> FloatWithMeasure<rounded>
let (+.) (x:Rounded) (y:Rounded) =
x + y |> round
let (-. ) (x:Rounded) (y:Rounded) =
x - y |> round
let (/.) (x:Rounded) (y:Rounded) =
x / y |> round
let ( *. ) (x:Rounded) (y:Rounded) =
x * y |> round
type RoundingWorkflow() =
/// NotRounded -> (Rounded->NotRounded) -> NotRounded
member this.Bind(result : NotRounded, rest : Rounded -> NotRounded) : NotRounded =
round result
|> rest
/// Rounded -> NotRounded
member this.Return (x:Rounded) : NotRounded = float x
let withPrecision sigDigs =
_sigDigs <- sigDigs
new RoundingWorkflow()
open RoundedCalculation
let rest : float =
withPrecision 3 {
let! x = 1.005
let! y = 2.004
let xPlusY = x +. y
let! a = 1.994
let! b = 0.995
let aMinusB = a -. b
let z = xPlusY *. aMinusB
return z
}
printfn "%f" rest
// 3.006000
b3BlbiBTeXN0ZW0Kb3BlbiBMYW5ndWFnZVByaW1pdGl2ZXMKCm1vZHVsZSBSb3VuZGVkQ2FsY3VsYXRpb24gPQogIFs8TWVhc3VyZT5dCiAgdHlwZSByb3VuZGVkCiAgdHlwZSBOb3RSb3VuZGVkID0gZmxvYXQKICB0eXBlIFJvdW5kZWQgPSBmbG9hdDxyb3VuZGVkPgoKICBsZXQgbXV0YWJsZSBfc2lnRGlncyA9IDAKCiAgbGV0IGlubGluZSByb3VuZCB4ID0gTWF0aC5Sb3VuZChmbG9hdCB4LCBfc2lnRGlncykgfD4gRmxvYXRXaXRoTWVhc3VyZTxyb3VuZGVkPgoKICBsZXQgKCsuKSAoeDpSb3VuZGVkKSAoeTpSb3VuZGVkKSA9CiAgICB4ICsgeSB8PiByb3VuZAogIGxldCAoLS4gKSAoeDpSb3VuZGVkKSAoeTpSb3VuZGVkKSA9CiAgICB4IC0geSB8PiByb3VuZAogIGxldCAoLy4pICh4OlJvdW5kZWQpICh5OlJvdW5kZWQpID0KICAgIHggLyB5IHw+IHJvdW5kCiAgbGV0ICggKi4gKSAoeDpSb3VuZGVkKSAoeTpSb3VuZGVkKSA9CiAgICB4ICogeSB8PiByb3VuZAoKCiAgdHlwZSBSb3VuZGluZ1dvcmtmbG93KCkgPQogICAgLy8vIE5vdFJvdW5kZWQgLT4gKFJvdW5kZWQtPk5vdFJvdW5kZWQpIC0+IE5vdFJvdW5kZWQKICAgIG1lbWJlciB0aGlzLkJpbmQocmVzdWx0IDogTm90Um91bmRlZCwgcmVzdCA6IFJvdW5kZWQgLT4gTm90Um91bmRlZCkgOiBOb3RSb3VuZGVkID0KICAgICAgcm91bmQgcmVzdWx0CiAgICAgIHw+IHJlc3QgCiAgICAvLy8gUm91bmRlZCAtPiBOb3RSb3VuZGVkICAgICAgICAgICAgICAgCiAgICBtZW1iZXIgdGhpcy5SZXR1cm4gKHg6Um91bmRlZCkgOiBOb3RSb3VuZGVkID0gZmxvYXQgeAoKICBsZXQgd2l0aFByZWNpc2lvbiBzaWdEaWdzID0KICAgIF9zaWdEaWdzIDwtIHNpZ0RpZ3MgCiAgICBuZXcgUm91bmRpbmdXb3JrZmxvdygpCgpvcGVuIFJvdW5kZWRDYWxjdWxhdGlvbgoKbGV0IHJlc3QgOiBmbG9hdCA9IAogIHdpdGhQcmVjaXNpb24gMyB7CiAgICBsZXQhIHggPSAxLjAwNQogICAgbGV0ISB5ID0gMi4wMDQKICAgIGxldCB4UGx1c1kgPSB4ICsuIHkKICAgIGxldCEgYSA9IDEuOTk0CiAgICBsZXQhIGIgPSAwLjk5NQogICAgbGV0IGFNaW51c0IgPSBhIC0uIGIKICAgIGxldCB6ID0geFBsdXNZICouIGFNaW51c0IKICAgIHJldHVybiB6CiAgfQoKcHJpbnRmbiAiJWYiIHJlc3QKLy8gMy4wMDYwMDA=