```
data Expr a
  = EVar Name
  | ENum Int
  | EConstr Int Int
  | EAp (Expr a) (Expr a)
  | ELet
      IsRec
      [(a, Expr a)]
      (Expr a)
  | ECase
      (Expr a)
      [Alter a]
  | ELam [a] (Expr a)
```

今天幾乎完成了 `pprint` ， `pprint` 把 `CoreProgram` 還有 `CoreExpr` 轉成中間格式 `Iseq` ，最後再轉成 `String` 。

```
data Iseq
  = INil
  | IStr String
  | IAppend Iseq Iseq
  | INewline
  | IIndent Iseq
```

`CoreExpr` 有 `EVar`, `ENum`, `EConstr`, `EAp`, `ELet`, `ECase`, `ELam` 七種 data constructor ，但排版用的 `Iseq` 只有 `INil`, `IStr`, `IAppend` 三種，就算加上未來的 `IIndent` 和 `INewline` 也不過五種。最後輸出的 `String` 就只有一種了。

可見 `pprint` 是個損失資訊的過程，資訊變少的新結構 `Iseq` 是專門為 pretty print 設計的，但原來的 `CoreExpr` 是為了直譯或是編譯而設計的。

在寫 `pprint` 時的錯誤少了，表示過去一年沒白寫吧？但繞了好多彎路。

---

加上了 `INewline` 和 `IIndent` ， `flatten` 時要多一個參數追蹤現在印到哪個 column ，但只在 `IIndent` 出現時，才真的把位移與當下的 `Iseq` 綁在一起。

接下來要為 infix operators 加上 precedence level ，並看情況補括號，棄用自動加括號的 `pprAExpr` 函數。
