infix operator 的 precendence 是寫死在文法中的。

才有書中 figure 1.3 這樣結構：

```
expr -> ...
     |  ...
     |  expr1

expr1 -> expr2 | expr1
      |  expr2
expr2 -> expr3 & expr2
      |  expr3
expr3 -> ...
```

直接寫起來會變成：

```
pExpr1 :: Parser CoreExpr
pExpr1
  = ((\e1 op e2 -> EAp (EAp (EVar op) e1) e2) `pFmap` pExpr2 `pAp` (pLit '|') `pAp` pExpr1) `pAlt`
    pExpr2
```

為了避免 `expr1` 不管成功或失敗，都各 parse `expr2` 一次，引進了新的資料結構： `PartialExpr` 。

```
data PartialExpr = NoOp | FoundOp Name CoreExpr
```

就可以寫成：

```
pExpr1 :: CoreExpr
pExpr1 = assembleOp `pFmap` pExpr2 `pAp` pExpr1c

pExpr1c :: PartialExpr
pExpr1c = (FoundOp `pFmap` (pLit "|") `pAp` pExpr1) `pAlt` (pEmpty NoOp)

pExpr2 :: CoreExpr
pExpr2 = assembleOp `pFmap` pExpr3 `pAp` pExpr2c

pExpr2c :: PartialExpr
pExpr2c = (FoundOp `pFmap` (pLit "&") `pAp` pExpr2) `pAlt` (pEmpty NoOp)

-- 略
```

而把 `PartialExpr` 組合成 `CoreExpr` ，則需要：

```
assembleOp :: CoreExpr -> PartialExpr -> CoreExpr
assembleOp e1 NoOp = e1
assembleOp e1 (FonudOp op e2) = EAp (EAp (EVar op) e1) e2
```

從現在的角度看，這讓我想起 `Maybe` ，但是 `CoreExpr` 和 `PartialExpr` 就算是 monoid ，也是兩種不同的 monoid ，如果真的要把它們接起來，那 `assembleOp` 對應的，會是現在的什麼函數呢？我還沒想清楚。
