Skip to content

Commit bee3ff9

Browse files
committed
feat: Added new chapters
1 parent 20f8410 commit bee3ff9

9 files changed

Lines changed: 1065 additions & 10 deletions

File tree

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
{
22
"cSpell.words": [
3+
"elif",
4+
"fastapi",
35
"Hashnode"
46
]
57
}

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This is a comprehensive guide to [Fable.Python](https://github.com/fable-compile
1212
4. **Compatibility** - Supported F# features and limitations
1313
5. **Fable v5** - What's new in Fable v5 for Python
1414
6. **Pydantic** - Pydantic interop with Decorate and ClassAttributes
15+
7. **Units of Measure** - Compile-time dimensional analysis
1516

1617
## The Meta Twist
1718

@@ -55,7 +56,8 @@ chapters/
5556
├── 03-bindings.fs # Python interop
5657
├── 04-compatibility.fs # F# feature support
5758
├── 05-fable-v5.fs # What's new in Fable v5
58-
└── 06-pydantic.fs # Pydantic interop
59+
├── 06-pydantic.fs # Pydantic interop
60+
└── 07-units-of-measure.fs # Dimensional analysis
5961
tools/
6062
├── fabletext.fs # Fabletext converter (F#)
6163
└── fabletext.fsproj

chapters/01-introduction.fs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,27 @@ F# is a functional-first language with powerful features like:
2222
- **Algebraic data types** - Model your domain precisely
2323
2424
With Fable.Python, you get all these benefits while targeting the Python ecosystem.
25-
This means you can:
2625
27-
1. Use F#'s type system and functional patterns
28-
2. Interop with Python libraries (NumPy, Pandas, etc.)
29-
3. Deploy anywhere Python runs - no .NET runtime needed
26+
## When to Use Fable.Python
27+
28+
Fable.Python is a great choice when:
29+
30+
- **Python ecosystem access** - You need AI/ML libraries (PyTorch, TensorFlow, LangChain),
31+
data science tools (Pandas, NumPy), or frameworks like Pydantic and FastAPI
32+
- **F# type safety** - You want pattern matching and exhaustive checking while using
33+
Python libraries
34+
- **Shared domain logic** - Write once in F#, run on .NET, JavaScript, Rust, and Python
35+
- **Publish to PyPI** - Your F# library can be available to the entire Python ecosystem
36+
- **Units of measure** - F#'s compile-time dimensional analysis prevents unit errors
37+
that Python can't catch
38+
39+
## When NOT to Use Fable.Python
40+
41+
- When your F# code depends on .NET libraries without Fable support
42+
- Performance-critical code (Python is still slow)
43+
- Team won't learn F#
44+
45+
**Best fit:** You love F#, but need Python's ecosystem.
3046
3147
## A Simple Example
3248

chapters/07-units-of-measure.fs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
(**
2+
# Units of Measure
3+
4+
One of F#'s most powerful features for scientific and engineering code is
5+
**units of measure** - compile-time dimensional analysis that prevents
6+
unit-related bugs.
7+
8+
## The Problem
9+
10+
Unit errors are a classic source of bugs. The famous Mars Climate Orbiter
11+
was lost because one team used metric units while another used imperial.
12+
Python can't catch these errors:
13+
14+
```python
15+
# Python - no protection
16+
distance = 100 # meters? feet? who knows!
17+
time = 9.58 # seconds? minutes?
18+
speed = distance / time # ???
19+
```
20+
21+
## F# Units of Measure
22+
23+
F# lets you annotate numeric types with units that are checked at compile time:
24+
*)
25+
26+
(*** hide ***)
27+
module UnitsOfMeasure
28+
29+
(**
30+
*)
31+
32+
[<Measure>] type m // meters
33+
[<Measure>] type s // seconds
34+
[<Measure>] type kg // kilograms
35+
36+
(**
37+
Now we can define values with units:
38+
*)
39+
40+
let distance = 100.0<m>
41+
let time = 9.58<s>
42+
let speed = distance / time // Automatically inferred as float<m/s>
43+
44+
(**
45+
The compiler tracks units through all operations. Division of meters by
46+
seconds gives meters-per-second. This is all checked at compile time!
47+
48+
## Preventing Errors
49+
50+
Try to add incompatible units and the compiler stops you:
51+
52+
```fsharp
53+
let distance = 100.0<m>
54+
let mass = 50.0<kg>
55+
56+
// This won't compile!
57+
// let nonsense = distance + mass
58+
// Error: The unit of measure 'm' does not match 'kg'
59+
```
60+
61+
## Derived Units
62+
63+
You can define derived units based on existing ones:
64+
*)
65+
66+
[<Measure>] type N = kg * m / s^2 // Newton
67+
[<Measure>] type J = N * m // Joule
68+
69+
let force = 10.0<N>
70+
let displacement = 5.0<m>
71+
let work = force * displacement // Inferred as float<J>
72+
73+
(**
74+
## Real-World Example: Physics Simulation
75+
76+
Here's a practical example computing kinetic energy:
77+
*)
78+
79+
let kineticEnergy (mass: float<kg>) (velocity: float<m/s>) : float<J> =
80+
0.5 * mass * velocity * velocity
81+
82+
let carMass = 1500.0<kg>
83+
let carSpeed = 30.0<m/s>
84+
let energy = kineticEnergy carMass carSpeed
85+
86+
(**
87+
The function signature clearly documents what units are expected and returned.
88+
The compiler ensures you can't accidentally pass velocity where mass is expected.
89+
90+
## Unit Conversions
91+
92+
Define conversion functions with explicit unit transformations:
93+
*)
94+
95+
[<Measure>] type km
96+
[<Measure>] type h
97+
98+
let metersToKm (d: float<m>) : float<km> = d / 1000.0<m/km>
99+
let secondsToHours (t: float<s>) : float<h> = t / 3600.0<s/h>
100+
101+
let marathonDistance = 42195.0<m>
102+
let marathonKm = metersToKm marathonDistance // 42.195<km>
103+
104+
(**
105+
## Generated Python
106+
107+
When compiled to Python, units are erased (they're purely a compile-time
108+
feature), but your code is guaranteed to be unit-safe:
109+
110+
```python
111+
def kinetic_energy(mass: float, velocity: float) -> float:
112+
return 0.5 * mass * velocity * velocity
113+
114+
car_mass: float = 1500.0
115+
car_speed: float = 30.0
116+
energy: float = kinetic_energy(car_mass, car_speed)
117+
```
118+
119+
The Python code is clean and efficient. All the unit checking happened
120+
at compile time in F#, so there's no runtime overhead.
121+
122+
## Why This Matters for Python
123+
124+
Python is widely used in scientific computing, but lacks compile-time
125+
unit checking. With Fable.Python, you can:
126+
127+
1. **Write unit-safe code** in F# with full dimensional analysis
128+
2. **Catch unit errors at compile time** before they become runtime bugs
129+
3. **Generate clean Python** that integrates with NumPy, SciPy, etc.
130+
4. **Document intent** - function signatures show expected units
131+
132+
This is especially valuable for physics simulations, financial calculations,
133+
engineering applications, and any domain where mixing up units could be costly.
134+
*)

0 commit comments

Comments
 (0)