https://github.com/rspeele/auto9g
Automatic 9th grader -- CAS at compile time for dead-simple business formulas
https://github.com/rspeele/auto9g
Last synced: 26 days ago
JSON representation
Automatic 9th grader -- CAS at compile time for dead-simple business formulas
- Host: GitHub
- URL: https://github.com/rspeele/auto9g
- Owner: rspeele
- License: mit
- Created: 2017-04-09T22:09:47.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2017-04-10T04:12:11.000Z (about 8 years ago)
- Last Synced: 2025-02-10T05:42:34.854Z (3 months ago)
- Language: F#
- Size: 217 KB
- Stars: 1
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Auto9G - automatic 9th grader
This is a minimal proof of concept for a really simple idea: compilers should perform trivial algebra for programmers.
Anybody who has used [Wolfram Alpha](https://www.wolframalpha.com/) knows that computers are great at solving equations.
Why, then, do the most commonly used programming languages require that programmers always manually rearrange formulas
to compute different variables?
Example: we have a system selling products with a fixed markup. The price we sell a product at is always the
cost of the product plus a markup factor (say, 0.1), like so:```fsharp
let priceOfOrder cost markup =
cost + cost * markup
```Occasionally a client asks for a product we don't already know the cost of, and a salesperson quotes them a custom price.
After we fulfill their order, we want to know whether we went below our usual markup, so we can generate an alert if a
salesperson is missing the markup on too many orders.To determine the effective markup of a custom price we might write code like:
```fsharp
let markupOfOrder cost price =
(price - cost) / cost
```But this violates [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) because really, it's the same formula.
We just did some basic algebra to move the variables around.If the requirements change so that we always have a base markup of 1 dollar, we have to change both formulas:
```fsharp
let priceOfOrder cost markup =
cost + cost * markup + 1let markupOfOrder cost price =
(price - 1 - cost) / cost
```Using this type provider, you would only change one place:
```fsharp
type MarkupFormula = Formula<"price = cost + cost * markup + 1">let priceOfOrder cost markup = MarkupFormula.price(cost = cost, markup = markup)
let markupOfOrder cost price = MarkupFormula.markup(cost = cost, price = price)
```# What it doesn't do
Since this is just a proof of concept, the following things are currently unsupported:
* Any equation that is more complex than a quadratic polynomial. This is why it's called auto 9th-grader, not auto
college-student. (Please do not contact me telling me that when you were in 9th grade you could do X, Y, or Z,
because I don't care). I have very little experience in CAS programming (consisting of this project's commit history),
so I am sure somebody else could improve on the basic concept with a bit more experience in that domain!* Decimal literals like 1.5. This is just a limitation of the parser, not the solver. You can easily work around
this by using a variable for those constants and supplying the variable value at runtime.* Calculations using types other than `System.Decimal`. I felt this was a reasonable default as it's what most .NET
programmers would use for business logic calculations. However, the solver produces a formula tree which could be
translated to a calculation on `float`s or an arbitrary precision `Rational` type, so any of those should be possible.