はい!
[a]
無料のモナドインスタンスとして表示できますFree ((,) a) ()
。
したがって、 EdwardKmettがFreeMonadsforLessで説明したスキームを適用できます。
取得するタイプは
newtype F a = F { runF :: forall r. (() -> r) -> ((a, r) -> r) -> r }
または単に
newtype F a = F { runF :: forall r. r -> (a -> r -> r) -> r }
だから私たちのリストrunF
の関数に他なりません!foldr
これはBoehm-Berarducciエンコーディングと呼ばれ、元のデータ型(リスト)と同型です。したがって、これは可能な限り小さいものです。
ネスは言う:
したがって、このタイプはまだ「幅が広い」ので、接頭辞だけでなく、g関数の引数を制約しません。
foldr
私が彼の議論を正しく理解していれば、彼は、 (またはrunF
)関数をととは異なるものに適用できる[]
と指摘しています(:)
。
foldr
しかし、 -encodingは連結にのみ使用できるとは決して主張しませんでした。確かに、この名前が示すように、あなたはそれを使って任意のフォールドを計算することができます—そしてそれはウィルネスが示したものです。
真のリストタイプが1つあることを少し忘れると、より明確になる可能性があります[a]
。リストタイプはたくさんあるかもしれません—例えば私は1つを定義することができます
data List a = Nil | Cons a (List a)
とは異なりますが、と同型[a]
です。
上記のfoldr
-encodingは、List a
またはのようなリストのさらに別のエンコーディングです[a]
。[a]
また、関数\l -> F (\a f -> foldr a f l)
と\x -> runF [] (:)
、それらの構成(どちらの順序でも)が同一であるという事実からも明らかなように、と同型です。ただし、に変換する必要はありません。を使用して直接に[a]
変換できます。List
\x -> runF x Nil Cons
重要な点は、一部のリストF a
の関数ではない要素が含まれていないことです。また、 (明らかに)複数のリストの関数である要素が含まれていないことも重要です。foldr
foldr
したがって、含まれる要素が少なすぎたり多すぎたりすることはありません。すべてのリストを正確に表すために必要な数の要素が正確に含まれています。
これは、差分リストエンコーディングには当てはまりません。たとえば、このreverse
関数はどのリストの追加操作でもありません。