>>403
書き換え規則の RULES プラグマですね。

たとえばソースに次のように記述すれば、reverse (reverse xs) という式は
最適化コンパイルの時に id xs に書き換えられます。
(引用符で囲んだ部分は規則の名前で、適当に名付けることができます)

{-# RULES "rev/rev" forall a. reverse (reverse a) = id a #-}

[ソースの記述] f xs = reverse (reverse xs)
[コンパイル後] f xs = id xs

簡単に言えば、書き換え規則中のイコールの左辺の「形」の式がソース中にあれば右辺に書き換えられます。

ただし、わざわざ「形」と強調したように、コンパイラは構文の形しか見ません。
ソース中の関数適用の式がアルファ変換(識別子名の置換)で書き換え規則左辺に変換できれば、
規則が適用されて右辺に書き換えられます。
ソース中の関数適用の式がベータ変換(簡約)でしか書き換え規則に変換左辺できなければ、
規則は適用されず書き換えられません。

たとえば先ほどの "rev/rev" の規則が記述されいても、次の式は書き換えられません。

[ソースの記述] g xs = (reverse . reverse) xs

ベータ変換(簡約)すれば、f xs も g xs も同じ意味の式になるのですが、これは無効です。
だから、これも書き換えるには、次の書き換え規則も記述しなければなりません。

{-# RULES "rev/rev 2" forall a. (.) reverse reverse a = id a #-}

中置演算は最適化時に関数適用に変換されてから、書き換え規則が適用できるか検証するみたいです。

詳しくは http://www.kotha.net/ghcguide_ja/latest/ の「7.19 書き換え規則」の項を見てください。