## テンソル内包表記で実現したかったこと

最初にテンソル内包表記を考案したのは、テンソル計算を縮約したかったからでした。
いくつかの次元をもったテンソルを特定の変数で縮約したかったのです。

### 動機：行列積の例

例えば、行列積 $C_{i,k} = \sum_j A_{i,j} \cdot B_{j,k}$ を考えます。

従来のループによる表現：
```python
for i in range(M):
    for k in range(P):
        for j in range(N):
            C[i, k] += A[i, j] * B[j, k]
```

ここで本質的に知りたいのは：
- **残したいインデックス**: `i`, `k`（出力テンソルの次元）
- **縮約するインデックス**: `j`（和を取って消える次元）

### テンソル内包表記の発想

そこで、「どのインデックスを残すか」を直接記述する方法を考えました：

```
[ i, k | { A[i, j] * B[j, k] } ]
```

この表記では：
- `[ i, k |` : 出力テンソルは `i` と `k` の2次元
- `A[i, j] * B[j, k]` : テンソル同士の積
- **暗黙の縮約**: `j` は出力に現れないので、自動的に和を取る

つまり、「残すインデックスだけを宣言」すれば、残りは自動的に縮約される、というのが最初の意図でした。

### アインシュタイン縮約記法との関係

これはアインシュタインの縮約記法（Einstein summation convention）と同じ発想です：

| 操作 | アインシュタイン記法 | テンソル内包表記 |
|------|---------------------|------------------|
| 行列積 | $C_{ik} = A_{ij}B_{jk}$ | `[ i, k \| { A[i,j] * B[j,k] } ]` |
| トレース | $\text{tr}(A) = A_{ii}$ | `[ \| { A[i,i] } ]` （スカラー） |
| 外積 | $C_{ij} = a_i b_j$ | `[ i, j \| { a[i] * b[j] } ]` |

### 現在の実装

現在のTL言語では、**ジェネレータを省略**してインデックスの範囲を**テンソルの形状から自動推論**できます：

```rust
let A = [i | i <- 0..5 { i }];  // 明示的なジェネレータ

let C = [i | { A[i] + 1 }];     // 暗黙的な範囲推論（Aの形状から）
```

上記の `C` の例では、`i` の範囲がテンソル `A` のアクセスパターンから自動的に推論されます。
これにより、当初理想とした「残すインデックスだけを宣言する」というシンプルな記法が実現しています。

---

## Haskellリスト内包表記からの影響

### 記法の由来

テンソル内包表記の構文は、**Haskellのリスト内包表記**から影響を受けています：

```haskell
-- Haskell: リスト内包表記
[ x * 2 | x <- [1..5] ]          -- [2, 4, 6, 8, 10]
[ (x, y) | x <- [1..3], y <- [1..3], x /= y ]  -- ペアのリスト
```

```rust
// TL: テンソル内包表記
[ i | i <- 0..5 { i * 2 } ]      // テンソル [0, 2, 4, 6, 8]
```

両者は `[ 出力 | ジェネレータ, フィルタ ]` という共通の構造を持ちます。

### ジェネレータの導入

Haskellのリスト内包表記には、**リストを生成する**機能があります。
この発想から、「テンソル内包表記を拡張すれば、テンソルの生成もできるだろう」と考え、**ジェネレータ**が実装されました。

つまり、テンソル内包表記の発展は以下の流れをたどりました：

1. **最初の発想**: 既存テンソルの縮約（`[ i, k | { A[i,j] * B[j,k] } ]`）
2. **Haskellからの影響**: ジェネレータによるテンソル生成（`[ i | i <- 0..N { expr } ]`）
3. **現在の形**: 両方の用途をサポート

これにより、テンソル内包表記は単なる縮約記法から、**テンソルの生成と変換を統一的に扱える表現**へと進化しました。
