# Design Note: Tensor Comprehension Semantics

## 議論: リスト内包表記 vs テンソル内包表記

### ユーザーからの指摘
`[i, j | i <- 0..N, j <- 0..N]` という式に対して、Haskellのリスト内包表記 `[(i, j) | i <- [0..N], j <- [0..N]]` は `[(0,0), (0,1), ..., (N,N)]` というフラットな1次元リスト（長さ N*N）を生成します。
一方、現在のTL言語の実装では、形状 `[N, N, 2]` のランク3テンソル（座標グリッド）を生成します。
ユーザーから「左側の `i, j` が反映されていないのでは？」「テンソルの場合はどうあるべきか熟慮せよ」との指摘がありました。

### 検討: テンソルとしての「自然」な解釈

テンソル内包表記（Tensor Comprehension）は、**多次元配列（テンソル）**を構築するための構文です。Haskellのリスト内包表記が「リスト（1次元の並び）」を生成するのに対し、テンソル内包表記は「インデックスと次元の対応関係」を重視すべきです。

#### 1. インデックスと次元の対応
数式における `A_{ij}` や、ループ構文 `for i in 0..N { for j in 0..M { ... } }` を考えたとき、`i` と `j` はそれぞれ独立した次元（行と列）に対応します。
したがって、`[i, j | ...]` と記述した場合、`i` は第1次元、`j` は第2次元を形成するのが、行列や画像を扱う上で最も直感的で強力です。

- **Haskell (List):** 全ての組み合わせを1列に並べる -> `Shape: [N * N]`
- **Tensor:** 組み合わせの空間構造（トポロジー）を維持する -> `Shape: [N, N]`

#### 2. 実例による比較

**例1: 単位行列の生成**
```rust
let I = [i, j | i <- 0..3, j <- 0..3 { if i == j { 1.0 } else { 0.0 } }];
```
- **多次元解釈 (採用案):** 結果は `3x3` 行列。そのまま行列演算 `I @ x` に使える。
- **フラット解釈:** 結果は長さ9のベクトル `[1, 0, 0, 0, 1, 0, 0, 0, 1]`。行列として使うには `reshape(3, 3)` が必須となる。

**例2: 画像のグラデーション**
```rust
let img = [x, y | x <- 0..W, y <- 0..H { x / W }];
```
- **多次元解釈 (採用案):** 結果は `[W, H]`（または `[W, H, 1]`）。そのまま画像として保存・表示できる。
- **フラット解釈:** 結果は `[W * H]` のピクセル列。空間的な隣接関係が失われる。

### 結論: 座標グリッド `[N, N, 2]` の正当性

現在の実装 `[i, j | ...]` (暗黙のボディ) が `[N, N, 2]` を返すのは、以下のロジックに基づいています。

1.  `i, j` という2つのジェネレータがあるため、ベースとなる空間は2次元 `[N, N]` である。
2.  暗黙のボディとして `[i, j]` (ベクトル) が採用されるため、各点 `(i, j)` に要素 `[i, j]` が配置される。
3.  結果として、`[N, N]` の空間に `Size 2` のベクトルが乗った `[N, N, 2]` となる。

これは `npmpy.meshgrid` や `torch.meshgrid` が生成するデータ構造（をスタックしたもの）と等価であり、ベクトル場やUV座標系を表現するのに最適な形式です。

### 方針
Haskellの「リスト」というデータ構造の制約に縛られず、**テンソルの「多次元性」という特性を最大限に活かす**ため、現在の「インデックス＝次元」というマッピングを仕様として採用します。
ユーザーの指摘する「左側の i, j」は、「フラットなリストの要素」としてではなく、「テンソルの直交する次元」として結果に反映されています。
