From 9f8a4567b97049a3c4dd6a96c3a4530f7a19c148 Mon Sep 17 00:00:00 2001
From: Marcel Luethi
Date: Tue, 29 Sep 2026 07:50:50 +0200
Subject: [PATCH 1/5] improve example in README
---
README.md | 36 +++++++++++++++++++++---------------
mdocs/README.md | 36 +++++++++++++++++++++---------------
2 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/README.md b/README.md
index 2a88b5d..04bff24 100644
--- a/README.md
+++ b/README.md
@@ -32,29 +32,35 @@ JAX and einops, and efficient implementations of tensor operations using JAX as
```scala
import dimwit.*
+import dimwit.autodiff.Autodiff
// Labels are simply Scala types
trait Batch derives Label
trait Feature derives Label
+trait Hidden derives Label
-// Create a 2D tensor with shape (3, 2), labeled with Batch and Feature
-val t = Tensor(
- Shape(Axis[Batch] -> 3, Axis[Feature] -> 2),
-).fromArray(
- Array(
- 1.0f, 2.0f,
- 3.0f, 4.0f,
- 5.0f, 6.0f
- )
+// Model parameters are plain case classes
+case class Params(w: Tensor2[Feature, Hidden, Float32], b: Tensor1[Hidden, Float32])
+
+// Write the model for a single example; axes are contracted by name, not position
+def layer(p: Params)(x: Tensor1[Feature, Float32]): Tensor1[Hidden, Float32] =
+ (x.dot(Axis[Feature])(p.w) + p.b).tanh
+
+// ... and lift it to a whole batch with vmap
+def loss(x: Tensor2[Batch, Feature, Float32])(p: Params): Tensor0[Float32] =
+ x.vmap(Axis[Batch])(layer(p)).pow(Tensor0(2.0f)).mean
+
+val x = Tensor(Shape(Axis[Batch] -> 32, Axis[Feature] -> 4)).fill(1.0f)
+val params = Params(
+ Tensor(Shape(Axis[Feature] -> 4, Axis[Hidden] -> 8)).fill(0.1f),
+ Tensor(Shape(Axis[Hidden] -> 8)).fill(0.0f)
)
-// Function to normalize a single feature vector
-def normalize(x: Tensor1[Feature, Float32]) : Tensor1[Feature, Float32] =
- (x -! x.mean) /! x.std
+// Gradients have the same structure and types as the parameters
+val grads: Params = Autodiff.grad(loss(x))(params).value
-// Apply the normalization function across the Batch dimension
-val normalized: Tensor2[Batch, Feature, Float32] =
- t.vmap(Axis[Batch])(normalize)
+// Mistakes are caught at compile time:
+// x.dot(Axis[Hidden])(params.w) // error: Axis[Hidden] not found in Tensor[(Batch, Feature)]
```
See our [quickstart guide](docs/quickstart.md) for a more detailed introduction to the core concepts and API and
diff --git a/mdocs/README.md b/mdocs/README.md
index fffb63f..7ee1d86 100644
--- a/mdocs/README.md
+++ b/mdocs/README.md
@@ -32,29 +32,35 @@ JAX and einops, and efficient implementations of tensor operations using JAX as
```scala mdoc:silent
import dimwit.*
+import dimwit.autodiff.Autodiff
// Labels are simply Scala types
trait Batch derives Label
trait Feature derives Label
+trait Hidden derives Label
-// Create a 2D tensor with shape (3, 2), labeled with Batch and Feature
-val t = Tensor(
- Shape(Axis[Batch] -> 3, Axis[Feature] -> 2),
-).fromArray(
- Array(
- 1.0f, 2.0f,
- 3.0f, 4.0f,
- 5.0f, 6.0f
- )
+// Model parameters are plain case classes
+case class Params(w: Tensor2[Feature, Hidden, Float32], b: Tensor1[Hidden, Float32])
+
+// Write the model for a single example; axes are contracted by name, not position
+def layer(p: Params)(x: Tensor1[Feature, Float32]): Tensor1[Hidden, Float32] =
+ (x.dot(Axis[Feature])(p.w) + p.b).tanh
+
+// ... and lift it to a whole batch with vmap
+def loss(x: Tensor2[Batch, Feature, Float32])(p: Params): Tensor0[Float32] =
+ x.vmap(Axis[Batch])(layer(p)).pow(Tensor0(2.0f)).mean
+
+val x = Tensor(Shape(Axis[Batch] -> 32, Axis[Feature] -> 4)).fill(1.0f)
+val params = Params(
+ Tensor(Shape(Axis[Feature] -> 4, Axis[Hidden] -> 8)).fill(0.1f),
+ Tensor(Shape(Axis[Hidden] -> 8)).fill(0.0f)
)
-// Function to normalize a single feature vector
-def normalize(x: Tensor1[Feature, Float32]) : Tensor1[Feature, Float32] =
- (x -! x.mean) /! x.std
+// Gradients have the same structure and types as the parameters
+val grads: Params = Autodiff.grad(loss(x))(params).value
-// Apply the normalization function across the Batch dimension
-val normalized: Tensor2[Batch, Feature, Float32] =
- t.vmap(Axis[Batch])(normalize)
+// Mistakes are caught at compile time:
+// x.dot(Axis[Hidden])(params.w) // error: Axis[Hidden] not found in Tensor[(Batch, Feature)]
```
See our [quickstart guide](docs/quickstart.md) for a more detailed introduction to the core concepts and API and
From 6817b447761621cff41a717f9cc4c366b4cba55a Mon Sep 17 00:00:00 2001
From: Benjamin Meyer
Date: Thu, 22 Oct 2026 14:21:10 +0200
Subject: [PATCH 2/5] Restructure README around the ScalaDays talk
Motivate DimWit in four points (strong types and fast execution, no
overhead under jit, names as shared vocabulary, explicit not implicit),
link the ScalaDays 2026 talk, show the talk's example next to JAX, and
list DeepWit and WitDraw as libraries built on DimWit.
Co-Authored-By: Claude Opus 5.5
---
README.md | 97 +++++++++++++++++++++++------------------
mdocs/README.md | 112 ++++++++++++++++++++++++++++++------------------
2 files changed, 126 insertions(+), 83 deletions(-)
diff --git a/README.md b/README.md
index 04bff24..305b0e7 100644
--- a/README.md
+++ b/README.md
@@ -9,62 +9,77 @@
-## Vision
+DimWit is a Scala library for numerical and machine learning programs that are easy for humans to understand.
+▶ Watch the [ScalaDays 2026 talk](https://www.youtube.com/watch?v=2ZwGhCWXN5g).
-We want to create a system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+## Why DimWit?
-## Why?
+- **Strong types and fast execution.** JAX executes fast, but its tensors are untyped. DimWit wraps JAX in Scala and names the dimensions of tensors in their types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
+- **No overhead under `jit`.** DimWit only traces a function once; the compiled XLA program then runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains on par with plain JAX.
+- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
+- **Explicit, not implicit.** DimWit is more than a one-to-one wrapper of JAX: what JAX does silently, DimWit makes explicit, e.g. broadcasting has its own operators (`x +! bias` instead of `x + bias`) and mixing precisions requires a cast (`x.asType(VType[Float16])`). In practice, this prevents many silent errors that are hard to find.
-AI coding agents and modern numerical libraries, such as Jax, Pytorch or Tensorflow, make it ever easier to write numerical and machine learning programs. Yet understanding remains as difficult as ever. Untyped code,
-opaque tensor operations and a focus on performance instead of clarity often obscure the concepts underlying the code.
-
-With *DimWit* we want to change this by
-- allowing to express concepts clearly and on a high level
-- leveraging the type system to enable the compiler to help us keep
- concepts separate and check correctness.
+## Example
-## How?
+A minimal example of what named dimensions add to a tensor program, next to the same program in JAX:
-DimWit uses the power of the Scala 3 type system to encode tensor dimensions as types. It combines this with a high-level API inspired by
-JAX and einops, and efficient implementations of tensor operations using JAX as a backend.
-
-## Example
+
+| DimWit | JAX |
+
+|
```scala
-import dimwit.*
-import dimwit.autodiff.Autodiff
-
-// Labels are simply Scala types
+// The axis names are the shared vocabulary
trait Batch derives Label
trait Feature derives Label
-trait Hidden derives Label
+trait Output derives Label
+
+// f has a strict signature: mapping a feature vector to an output vector
+def f(x: Tensor1[Feature, Float32]): Tensor1[Output, Float32] = ...
+
+// Tensor types carry meaning and are tracked by the compiler
+val X: Tensor2[Batch, Feature, Float32] = ...
+val Y: Tensor2[Batch, Output, Float32] =
+ X.vmap(Axis[Batch])(f) // the axis by name, not position
+```
+
+ |
+
-// Model parameters are plain case classes
-case class Params(w: Tensor2[Feature, Hidden, Float32], b: Tensor1[Hidden, Float32])
+```python
-// Write the model for a single example; axes are contracted by name, not position
-def layer(p: Params)(x: Tensor1[Feature, Float32]): Tensor1[Hidden, Float32] =
- (x.dot(Axis[Feature])(p.w) + p.b).tanh
-// ... and lift it to a whole batch with vmap
-def loss(x: Tensor2[Batch, Feature, Float32])(p: Params): Tensor0[Float32] =
- x.vmap(Axis[Batch])(layer(p)).pow(Tensor0(2.0f)).mean
-val x = Tensor(Shape(Axis[Batch] -> 32, Axis[Feature] -> 4)).fill(1.0f)
-val params = Params(
- Tensor(Shape(Axis[Feature] -> 4, Axis[Hidden] -> 8)).fill(0.1f),
- Tensor(Shape(Axis[Hidden] -> 8)).fill(0.0f)
-)
-// Gradients have the same structure and types as the parameters
-val grads: Params = Autodiff.grad(loss(x))(params).value
-// Mistakes are caught at compile time:
-// x.dot(Axis[Hidden])(params.w) // error: Axis[Hidden] not found in Tensor[(Batch, Feature)]
+
+def f(x: Tensor) -> Tensor: ...
+
+
+X: Tensor = ...
+Y: Tensor = (
+ jax.vmap(f, in_axes=0)(X))
```
+ |
+
+
+
+In DimWit, the names state the intent of the code; in JAX, the reader has to infer it from axis positions.
+
+
See our [quickstart guide](docs/quickstart.md) for a more detailed introduction to the core concepts and API and
-check out the [examples](examples/src/main/scala).
+check out the [examples](examples/src/main/scala).
+
+## Scope
+
+Like JAX, DimWit is a library for fast numerical programming: tensors, automatic differentiation, `vmap`, `jit` and random numbers.
+Everything else is built on top of it:
+
+| Project | Description |
+|---|---|
+| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
+| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
## Using DimWit as a Library
@@ -130,10 +145,8 @@ Alternatively, you can configure the Python environment manually using these env
## Status
-**Early but functional.** DimWit successfully runs complex models including GPT-2 (see [example](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt)). The core concepts are stable, but the API is still evolving.
-
-**Not production-ready** - expect breaking changes.
+**Ready to use.** The core concepts are stable and the API is maturing, but breaking changes may still happen until 1.0.
## Contributing
-If your interests align with our vision, we would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
+We would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
diff --git a/mdocs/README.md b/mdocs/README.md
index 7ee1d86..715254d 100644
--- a/mdocs/README.md
+++ b/mdocs/README.md
@@ -9,62 +9,94 @@
-## Vision
+DimWit is a Scala library for numerical and machine learning programs that are easy for humans to understand.
+▶ Watch the [ScalaDays 2026 talk](https://www.youtube.com/watch?v=2ZwGhCWXN5g).
-We want to create a system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+## Why DimWit?
-## Why?
+- **Strong types and fast execution.** JAX executes fast, but its tensors are untyped. DimWit wraps JAX in Scala and names the dimensions of tensors in their types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
+- **No overhead under `jit`.** DimWit only traces a function once; the compiled XLA program then runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains on par with plain JAX.
+- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
+- **Explicit, not implicit.** DimWit is more than a one-to-one wrapper of JAX: what JAX does silently, DimWit makes explicit, e.g. broadcasting has its own operators (`x +! bias` instead of `x + bias`) and mixing precisions requires a cast (`x.asType(VType[Float16])`). In practice, this prevents many silent errors that are hard to find.
-AI coding agents and modern numerical libraries, such as Jax, Pytorch or Tensorflow, make it ever easier to write numerical and machine learning programs. Yet understanding remains as difficult as ever. Untyped code,
-opaque tensor operations and a focus on performance instead of clarity often obscure the concepts underlying the code.
+## Example
+
+A minimal example of what named dimensions add to a tensor program, next to the same program in JAX:
+
+
+| DimWit | JAX |
+
+|
+
+```scala
+// The axis names are the shared vocabulary
+trait Batch derives Label
+trait Feature derives Label
+trait Output derives Label
+
+// f has a strict signature: mapping a feature vector to an output vector
+def f(x: Tensor1[Feature, Float32]): Tensor1[Output, Float32] = ...
+
+// Tensor types carry meaning and are tracked by the compiler
+val X: Tensor2[Batch, Feature, Float32] = ...
+val Y: Tensor2[Batch, Output, Float32] =
+ X.vmap(Axis[Batch])(f) // the axis by name, not position
+```
+
+ |
+
+
+```python
-With *DimWit* we want to change this by
-- allowing to express concepts clearly and on a high level
-- leveraging the type system to enable the compiler to help us keep
- concepts separate and check correctness.
-## How?
-DimWit uses the power of the Scala 3 type system to encode tensor dimensions as types. It combines this with a high-level API inspired by
-JAX and einops, and efficient implementations of tensor operations using JAX as a backend.
-## Example
-```scala mdoc:silent
+
+def f(x: Tensor) -> Tensor: ...
+
+
+X: Tensor = ...
+Y: Tensor = (
+ jax.vmap(f, in_axes=0)(X))
+```
+
+ |
+
+
+
+In DimWit, the names state the intent of the code; in JAX, the reader has to infer it from axis positions.
+
+```scala mdoc:invisible
+// Compiles the DimWit example above
import dimwit.*
-import dimwit.autodiff.Autodiff
-// Labels are simply Scala types
trait Batch derives Label
trait Feature derives Label
-trait Hidden derives Label
+trait Output derives Label
-// Model parameters are plain case classes
-case class Params(w: Tensor2[Feature, Hidden, Float32], b: Tensor1[Hidden, Float32])
+val A: Tensor2[Feature, Output, Float32] = Tensor2(Axis[Feature], Axis[Output]).fromArray(Array(Array(0f, -1f, 0f), Array(1f, 2f, 2f)))
-// Write the model for a single example; axes are contracted by name, not position
-def layer(p: Params)(x: Tensor1[Feature, Float32]): Tensor1[Hidden, Float32] =
- (x.dot(Axis[Feature])(p.w) + p.b).tanh
+def f(x: Tensor1[Feature, Float32]): Tensor1[Output, Float32] =
+ x.dot(Axis[Feature])(A)
-// ... and lift it to a whole batch with vmap
-def loss(x: Tensor2[Batch, Feature, Float32])(p: Params): Tensor0[Float32] =
- x.vmap(Axis[Batch])(layer(p)).pow(Tensor0(2.0f)).mean
+val X: Tensor2[Batch, Feature, Float32] = Tensor2(Axis[Batch], Axis[Feature]).fromArray(Array(Array(1f, 2f), Array(3f, 4f), Array(5f, 6f)))
+val Y: Tensor2[Batch, Output, Float32] =
+ X.vmap(Axis[Batch])(f)
+```
-val x = Tensor(Shape(Axis[Batch] -> 32, Axis[Feature] -> 4)).fill(1.0f)
-val params = Params(
- Tensor(Shape(Axis[Feature] -> 4, Axis[Hidden] -> 8)).fill(0.1f),
- Tensor(Shape(Axis[Hidden] -> 8)).fill(0.0f)
-)
+See our [quickstart guide](docs/quickstart.md) for a more detailed introduction to the core concepts and API and
+check out the [examples](examples/src/main/scala).
-// Gradients have the same structure and types as the parameters
-val grads: Params = Autodiff.grad(loss(x))(params).value
+## Scope
-// Mistakes are caught at compile time:
-// x.dot(Axis[Hidden])(params.w) // error: Axis[Hidden] not found in Tensor[(Batch, Feature)]
-```
+Like JAX, DimWit is a library for fast numerical programming: tensors, automatic differentiation, `vmap`, `jit` and random numbers.
+Everything else is built on top of it:
-See our [quickstart guide](docs/quickstart.md) for a more detailed introduction to the core concepts and API and
-check out the [examples](examples/src/main/scala).
+| Project | Description |
+|---|---|
+| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
+| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
## Using DimWit as a Library
@@ -130,10 +162,8 @@ Alternatively, you can configure the Python environment manually using these env
## Status
-**Early but functional.** DimWit successfully runs complex models including GPT-2 (see [example](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt)). The core concepts are stable, but the API is still evolving.
-
-**Not production-ready** - expect breaking changes.
+**Ready to use.** The core concepts are stable and the API is maturing, but breaking changes may still happen until 1.0.
## Contributing
-If your interests align with our vision, we would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
+We would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
From 8a9f89c96fc6ae055eaf200cbafb780c0bc93af1 Mon Sep 17 00:00:00 2001
From: Benjamin Meyer
Date: Fri, 23 Oct 2026 09:41:00 +0200
Subject: [PATCH 3/5] Add feedback Marcel
---
README.md | 28 ++++++++++++++++------------
mdocs/README.md | 28 ++++++++++++++++------------
2 files changed, 32 insertions(+), 24 deletions(-)
diff --git a/README.md b/README.md
index 305b0e7..ecbc7f7 100644
--- a/README.md
+++ b/README.md
@@ -12,9 +12,13 @@
DimWit is a Scala library for numerical and machine learning programs that are easy for humans to understand.
▶ Watch the [ScalaDays 2026 talk](https://www.youtube.com/watch?v=2ZwGhCWXN5g).
+## Vision
+
+We want to create a system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+
## Why DimWit?
-- **Strong types and fast execution.** JAX executes fast, but its tensors are untyped. DimWit wraps JAX in Scala and names the dimensions of tensors in their types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
+- **Strong types and fast execution.** Numerical programs need to run fast, but they also need to be understood. JAX runs fast, but with untyped tensors the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
- **No overhead under `jit`.** DimWit only traces a function once; the compiled XLA program then runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains on par with plain JAX.
- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
- **Explicit, not implicit.** DimWit is more than a one-to-one wrapper of JAX: what JAX does silently, DimWit makes explicit, e.g. broadcasting has its own operators (`x +! bias` instead of `x + bias`) and mixing precisions requires a cast (`x.asType(VType[Float16])`). In practice, this prevents many silent errors that are hard to find.
@@ -71,16 +75,6 @@ In DimWit, the names state the intent of the code; in JAX, the reader has to inf
See our [quickstart guide](docs/quickstart.md) for a more detailed introduction to the core concepts and API and
check out the [examples](examples/src/main/scala).
-## Scope
-
-Like JAX, DimWit is a library for fast numerical programming: tensors, automatic differentiation, `vmap`, `jit` and random numbers.
-Everything else is built on top of it:
-
-| Project | Description |
-|---|---|
-| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
-| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
-
## Using DimWit as a Library
### Requirements
@@ -143,10 +137,20 @@ Alternatively, you can configure the Python environment manually using these env
- `DIMWIT_PYTHON_LIBRARY` — path to the Python shared library (find it with `python3 -c "import ctypes.util; print(ctypes.util.find_library('python3'))"`)
- `DIMWIT_SKIP_SYNC` — set to `true` to skip uv environment sync on startup
+## Scope
+
+Like JAX, DimWit is a library for fast numerical programming: tensors, automatic differentiation, `vmap`, `jit` and random numbers.
+Everything else is built on top of it:
+
+| Project | Description |
+|---|---|
+| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
+| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
+
## Status
**Ready to use.** The core concepts are stable and the API is maturing, but breaking changes may still happen until 1.0.
## Contributing
-We would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
+If your interests align with our vision, we would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
diff --git a/mdocs/README.md b/mdocs/README.md
index 715254d..d359a4b 100644
--- a/mdocs/README.md
+++ b/mdocs/README.md
@@ -12,9 +12,13 @@
DimWit is a Scala library for numerical and machine learning programs that are easy for humans to understand.
▶ Watch the [ScalaDays 2026 talk](https://www.youtube.com/watch?v=2ZwGhCWXN5g).
+## Vision
+
+We want to create a system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+
## Why DimWit?
-- **Strong types and fast execution.** JAX executes fast, but its tensors are untyped. DimWit wraps JAX in Scala and names the dimensions of tensors in their types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
+- **Strong types and fast execution.** Numerical programs need to run fast, but they also need to be understood. JAX runs fast, but with untyped tensors the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
- **No overhead under `jit`.** DimWit only traces a function once; the compiled XLA program then runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains on par with plain JAX.
- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
- **Explicit, not implicit.** DimWit is more than a one-to-one wrapper of JAX: what JAX does silently, DimWit makes explicit, e.g. broadcasting has its own operators (`x +! bias` instead of `x + bias`) and mixing precisions requires a cast (`x.asType(VType[Float16])`). In practice, this prevents many silent errors that are hard to find.
@@ -88,16 +92,6 @@ val Y: Tensor2[Batch, Output, Float32] =
See our [quickstart guide](docs/quickstart.md) for a more detailed introduction to the core concepts and API and
check out the [examples](examples/src/main/scala).
-## Scope
-
-Like JAX, DimWit is a library for fast numerical programming: tensors, automatic differentiation, `vmap`, `jit` and random numbers.
-Everything else is built on top of it:
-
-| Project | Description |
-|---|---|
-| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
-| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
-
## Using DimWit as a Library
### Requirements
@@ -160,10 +154,20 @@ Alternatively, you can configure the Python environment manually using these env
- `DIMWIT_PYTHON_LIBRARY` — path to the Python shared library (find it with `python3 -c "import ctypes.util; print(ctypes.util.find_library('python3'))"`)
- `DIMWIT_SKIP_SYNC` — set to `true` to skip uv environment sync on startup
+## Scope
+
+Like JAX, DimWit is a library for fast numerical programming: tensors, automatic differentiation, `vmap`, `jit` and random numbers.
+Everything else is built on top of it:
+
+| Project | Description |
+|---|---|
+| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
+| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
+
## Status
**Ready to use.** The core concepts are stable and the API is maturing, but breaking changes may still happen until 1.0.
## Contributing
-We would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
+If your interests align with our vision, we would love to have you on board! Feel free to open issues or pull requests on GitHub.
\ No newline at end of file
From 64819bb36265caccd6f1dfd1e930be50918af5fb Mon Sep 17 00:00:00 2001
From: Benjamin Meyer
Date: Fri, 23 Oct 2026 10:33:35 +0200
Subject: [PATCH 4/5] Update the Why. Layout.
---
README.md | 37 ++++++++++++++++++-------------------
mdocs/README.md | 37 ++++++++++++++++++-------------------
2 files changed, 36 insertions(+), 38 deletions(-)
diff --git a/README.md b/README.md
index ecbc7f7..e18b1ca 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,26 @@
# DimWit - Tensor programming with wit
-> Programming is the art of telling another human being what one wants the computer to do.
->
-> Donald Knuth
-
-
-
-
-
-
-DimWit is a Scala library for numerical and machine learning programs that are easy for humans to understand.
-▶ Watch the [ScalaDays 2026 talk](https://www.youtube.com/watch?v=2ZwGhCWXN5g).
-
-## Vision
-
-We want to create a system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+
+
+
+
+ |
+
+ “Programming is the art of telling another human being what one wants the computer to do.” — Donald Knuth
+ Vision: A system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+ ▶ Watch the ScalaDays 2026 talk.
+ |
+
+
## Why DimWit?
-- **Strong types and fast execution.** Numerical programs need to run fast, but they also need to be understood. JAX runs fast, but with untyped tensors the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
-- **No overhead under `jit`.** DimWit only traces a function once; the compiled XLA program then runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains on par with plain JAX.
+Why yet another tensor library? In the era of AI-generated code, types make high-level relations clear at a glance and code easier to review. DimWit adds them to tensor code, at the runtime speed of JAX:
+
+- **Easier to understand, easier to review.** With untyped tensors, the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so whoever reads or reviews the code sees what each axis means, and the compiler checks it.
+- **Fast.** DimWit is on par with JAX: under `jit`, a function is traced once and the compiled XLA program runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains as fast as in plain JAX.
- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
-- **Explicit, not implicit.** DimWit is more than a one-to-one wrapper of JAX: what JAX does silently, DimWit makes explicit, e.g. broadcasting has its own operators (`x +! bias` instead of `x + bias`) and mixing precisions requires a cast (`x.asType(VType[Float16])`). In practice, this prevents many silent errors that are hard to find.
+- **Fewer silent bugs.** Implicit broadcasting and type promotion usually do the right thing, but when they don't, the code still runs and silently produces wrong results. DimWit makes both explicit (e.g. `x +! bias`), expressing intent and preventing many silent bugs. Instant compile errors streamline the writing of explicit code.
## Example
@@ -144,7 +143,7 @@ Everything else is built on top of it:
| Project | Description |
|---|---|
-| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
+| [DeepWit](https://github.com/dimwit-dev/deepwit) | Functional deep learning library providing core modules and examples. |
| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
## Status
diff --git a/mdocs/README.md b/mdocs/README.md
index d359a4b..a1ad5f5 100644
--- a/mdocs/README.md
+++ b/mdocs/README.md
@@ -1,27 +1,26 @@
# DimWit - Tensor programming with wit
-> Programming is the art of telling another human being what one wants the computer to do.
->
-> Donald Knuth
-
-
-
-
-
-
-DimWit is a Scala library for numerical and machine learning programs that are easy for humans to understand.
-▶ Watch the [ScalaDays 2026 talk](https://www.youtube.com/watch?v=2ZwGhCWXN5g).
-
-## Vision
-
-We want to create a system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+
+
+
+
+ |
+
+ “Programming is the art of telling another human being what one wants the computer to do.” — Donald Knuth
+ Vision: A system for writing numerical and machine learning programs that puts human understanding first. While programming, the compiler should help us to keep concepts separate and sharpen our thinking about the problem.
+ ▶ Watch the ScalaDays 2026 talk.
+ |
+
+
## Why DimWit?
-- **Strong types and fast execution.** Numerical programs need to run fast, but they also need to be understood. JAX runs fast, but with untyped tensors the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so the code says what each axis means and the compiler checks it.
-- **No overhead under `jit`.** DimWit only traces a function once; the compiled XLA program then runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains on par with plain JAX.
+Why yet another tensor library? In the era of AI-generated code, types make high-level relations clear at a glance and code easier to review. DimWit adds them to tensor code, at the runtime speed of JAX:
+
+- **Easier to understand, easier to review.** With untyped tensors, the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so whoever reads or reviews the code sees what each axis means, and the compiler checks it.
+- **Fast.** DimWit is on par with JAX: under `jit`, a function is traced once and the compiled XLA program runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains as fast as in plain JAX.
- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
-- **Explicit, not implicit.** DimWit is more than a one-to-one wrapper of JAX: what JAX does silently, DimWit makes explicit, e.g. broadcasting has its own operators (`x +! bias` instead of `x + bias`) and mixing precisions requires a cast (`x.asType(VType[Float16])`). In practice, this prevents many silent errors that are hard to find.
+- **Fewer silent bugs.** Implicit broadcasting and type promotion usually do the right thing, but when they don't, the code still runs and silently produces wrong results. DimWit makes both explicit (e.g. `x +! bias`), expressing intent and preventing many silent bugs. Instant compile errors streamline the writing of explicit code.
## Example
@@ -161,7 +160,7 @@ Everything else is built on top of it:
| Project | Description |
|---|---|
-| [DeepWit](https://github.com/dimwit-dev/deepwit) | Type-safe deep learning library with layers, attention and GPT-2. |
+| [DeepWit](https://github.com/dimwit-dev/deepwit) | Functional deep learning library providing core modules and examples. |
| [WitDraw](https://github.com/dimwit-dev/witdraw) | Experimental library for probabilistic programming. |
## Status
From 851e2690bb27203f7cb445d776d1e13542741581 Mon Sep 17 00:00:00 2001
From: Benjamin Meyer
Date: Fri, 23 Oct 2026 10:54:32 +0200
Subject: [PATCH 5/5] Furhter clean up the Why
---
README.md | 8 ++++----
mdocs/README.md | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index e18b1ca..05a0976 100644
--- a/README.md
+++ b/README.md
@@ -15,12 +15,12 @@
## Why DimWit?
-Why yet another tensor library? In the era of AI-generated code, types make high-level relations clear at a glance and code easier to review. DimWit adds them to tensor code, at the runtime speed of JAX:
+Why yet another tensor library? With untyped tensors, the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, without sacrificing runtime speed:
-- **Easier to understand, easier to review.** With untyped tensors, the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so whoever reads or reviews the code sees what each axis means, and the compiler checks it.
+- **Easier to understand.** Concepts become types, so the compiler helps keep them apart, sharpening the thinking about the problem.
+- **Easier to review.** The meaning of each axis is part of the code, streamlining code reviews, which matters all the more in the era of AI-generated code.
+- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain, so the code reads close to the theory behind it. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
- **Fast.** DimWit is on par with JAX: under `jit`, a function is traced once and the compiled XLA program runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains as fast as in plain JAX.
-- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
-- **Fewer silent bugs.** Implicit broadcasting and type promotion usually do the right thing, but when they don't, the code still runs and silently produces wrong results. DimWit makes both explicit (e.g. `x +! bias`), expressing intent and preventing many silent bugs. Instant compile errors streamline the writing of explicit code.
## Example
diff --git a/mdocs/README.md b/mdocs/README.md
index a1ad5f5..c9a17fb 100644
--- a/mdocs/README.md
+++ b/mdocs/README.md
@@ -15,12 +15,12 @@
## Why DimWit?
-Why yet another tensor library? In the era of AI-generated code, types make high-level relations clear at a glance and code easier to review. DimWit adds them to tensor code, at the runtime speed of JAX:
+Why yet another tensor library? With untyped tensors, the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, without sacrificing runtime speed:
-- **Easier to understand, easier to review.** With untyped tensors, the meaning of each axis lives only in the programmer's head. DimWit puts it into the types, e.g. `Tensor2[Batch, Feature, Float32]`, so whoever reads or reviews the code sees what each axis means, and the compiler checks it.
+- **Easier to understand.** Concepts become types, so the compiler helps keep them apart, sharpening the thinking about the problem.
+- **Easier to review.** The meaning of each axis is part of the code, streamlining code reviews, which matters all the more in the era of AI-generated code.
+- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain, so the code reads close to the theory behind it. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
- **Fast.** DimWit is on par with JAX: under `jit`, a function is traced once and the compiled XLA program runs without Scala in the loop. [GPT-2 in DimWit](https://github.com/dimwit-dev/deepwit/tree/main/examples/src/main/scala/deepwit/examples/gpt) (124M parameters, trained from scratch on 10B tokens) trains as fast as in plain JAX.
-- **Names are a shared vocabulary.** Axes like `Batch` or `Feature` name the concepts of the domain. They become a shared vocabulary for your team and your AI agents, whether you discuss code, review it or prompt for it.
-- **Fewer silent bugs.** Implicit broadcasting and type promotion usually do the right thing, but when they don't, the code still runs and silently produces wrong results. DimWit makes both explicit (e.g. `x +! bias`), expressing intent and preventing many silent bugs. Instant compile errors streamline the writing of explicit code.
## Example