これらの用語は私の大学のコースで言及されました。クイックグーグルで大学の論文をいくつか指摘されましたが、簡単な説明を探しています。
C
は、あるカテゴリのオブジェクト(たとえばCC
)でF
あり、ファンクタであるCC -> CC
ため、それCC
自体にマップされます。これF CC -> CC
は、カテゴリ内の通常の矢印CC
です。だからF
代数はオブジェクトでありC : CC
、矢印F C -> C
でCC
これらの用語は私の大学のコースで言及されました。クイックグーグルで大学の論文をいくつか指摘されましたが、簡単な説明を探しています。
C
は、あるカテゴリのオブジェクト(たとえばCC
)でF
あり、ファンクタであるCC -> CC
ため、それCC
自体にマップされます。これF CC -> CC
は、カテゴリ内の通常の矢印CC
です。だからF
代数はオブジェクトでありC : CC
、矢印F C -> C
でCC
回答:
すでに2つの答えが提供されていますが、ここでは「バナナの分裂」については説明されていないと思います。
実際、「バナナ、レンズ、エンベロープ、有刺鉄線を使用した関数型プログラミング、Erik Meijer Maarten Fokkinga、Ross Paterson、1991」で定義されています。その記事は、Squiggolを多用しているため、読みにくいです(私にとって)。ただし、「フォールドの普遍性と表現力に関するチュートリアル、Graham Hutton、1999」には、解析しやすい定義が含まれています。
foldを使用してタプルを生成する簡単な最初の例として、数値リストの合計と長さを計算する関数sumlengthを考えます。
sumlength :: [Int] → (Int,Int) sumlength xs = (sum xs, length xs)
前に示したfoldを使用した関数sumとlengthの定義の単純な組み合わせにより、関数sumlengthは、数値のリストから数値のペアを生成するfoldの単一のアプリケーションとして再定義できます。
sumlength = fold (λn (x, y) → (n + x, 1 + y)) (0, 0)
この定義は、2つの別個のトラバーサルではなく、引数リストに対して1つのトラバーサルのみを行うため、元の定義よりも効率的です。この例から一般化、のアプリケーションの任意のペア倍同じリストには、常に、単一のアプリケーション与えるために組み合わせることができる折り畳みのいわゆる「バナナスプリット」プロパティにアピールすることで、ペアを生成倍(マイヤー、1992) 。このプロパティの奇妙な名前は、折り演算子がバナナに似た括弧(| |)を使用して記述され、ペア演算子が分割と呼ばれることもあるという事実に由来しています。したがって、それらの組み合わせはバナナスプリットと呼ばれます!
つまり、これは実際にはMeijerと「バナナ、レンズ、エンベロープ、および有刺鉄線を使用した関数型プログラミング」と呼ばれる他のいくつかの論文を参照しています。基本的な考え方は、
data List = Cons Int List | Nil
そして、再帰を型変数に分解することができます
data ListF a = Cons Int a | Nil
F
これを追加した理由は、これが今ではファンクターだからです!また、リストを模倣することもできますが、ひねりを加えて:リストを作成するには、リストタイプをネストする必要があります
type ThreeList = ListF (ListF (ListF Void)))
元のリストを復元するには、これを無限にネストし続ける必要があります。それは私たちにタイプ与えるListFF
場所を
ListF ListFF == ListFF
これを行うには、「固定小数点タイプ」を定義します
data Fix f = Fix {unfix :: f (Fix f)}
type ListFF = Fix ListF
演習として、これが上記の式を満たしていることを確認する必要があります。これで、最終的にバナナ(異形)を定義できます。
type ListAlg a = ListF a -> a
ListAlg
sは「リスト代数」のタイプであり、特定の関数を定義できます
cata :: ListAlg a -> ListFF -> a
cata f = f . fmap (cata f) . unfix
さらにもっと
cata :: ListAlg a -> ListFF -> a
cata :: (Either () (Int, a) -> a) -> ListFF -> a
cata :: (() -> a) -> ((Int, a) -> a) -> ListFF -> a
cata :: a -> (Int -> a -> a) -> ListFF -> a
cata :: (Int -> a -> a) -> a -> [Int] -> a
見覚えがあります?cata
右折りとまったく同じです!
本当に興味深いのは、この「ファンクターの固定点」で定義されたタイプにはリストだけでなく、リストを超えてこれを実行できることcata
と、それらすべてを受け入れるためにタイプシグネチャを緩和するだけです。
cata :: (f a -> a) -> Fix f -> a
これは実際に私が書いたカテゴリー理論からインスピレーションを受けていますが、これはHaskell側の要です。
jozefgが答えを提供しましたが、質問に答えたかどうかはわかりません。「融合の法則」は次の論文で説明されています。
折り畳みの普遍性と表現力に関するチュートリアル、GRAHAM HUTTON、1999
基本的に、ある条件下では、関数の構成を結合(「融合」)して単一の折り畳みに折り畳むことができると言われているので、基本的に
h・fold gw = fold fv
この平等の条件は
hw = v
h(gxy)= fx(hy)
「バナナスプリット」または「バナナスプリット法」は、記事からのものです
バナナ、レンズ、エンベロープ、有刺鉄線を使用した関数型プログラミング、Erik Meijer Maarten Fokkinga、Ross Paterson、1991
残念ながら、Bird-Meertensの形式を使用しているため、この記事を解読するのは非常に困難です。「バナナ分割法」を理解している限り、同じ引数で2つのフォールドが動作している場合、それらを1つのフォールドにマージできると述べています。