今のところ、夢はまだ続きます。Haskell の概念を学ぶたびに、私はより魅力的になります。それでも、カタモルフィズムに関する以前の質問に対するこの貴重な@luquiの回答に完全に取り組んでいないので、問題が解決するまで戻ってきます。ウィキペディアのこのサンプル コードについてで、BINARY ツリーのカタモルフィズムを扱っています。
それにもかかわらず、 NON BINARYツリーにカタモルフィズムを実装しようとしましたが、いくつかの問題に直面しています。
data Composition a = Leaf a
| Composite [Composition a]
data CompositionAlgebra a r = CompositionAlgebra { leaf :: a → r
, composite :: [r] → r }
foldComposition :: CompositionAlgebra a r → Composition a → r
foldComposition a@(CompositionAlgebra {leaf = f}) (Leaf x ) = f x
foldComposition a@(CompositionAlgebra {composite = g}) (Composite [y]) = map g [y]
-- その最新行は "map g [y]" で ghc を喜ばせません
maxOfPair :: a → a → a
maxOfPair x y = if( x > y) -- this doesnt please ghc either, Ordering trouble
then (x)
else (y)
maxInList :: [a] → a
maxInList (x:xs) = maxOfPair x (maxInList xs)
treeDepth :: CompositionAlgebra a Integer
treeDepth = CompositionAlgebra { leaf = const 1, composite = λx → 1 + maxInList x }
sumTree :: (Num a) ⇒ CompositionAlgebra a a
sumTree = CompositionAlgebra { leaf = id, composite = (+) }
-- そして、この最新の sumTree は ghc でも間違っています
C++ 演算子の > と + と同じように > と + が表示されます。だから私は、オブジェクトを実装するオブジェクトを与えることなく、ghcが私に怒っていることを理解していません >/+ かどうか。
次に、パターン マッチングのガイドのように見える => (-> ??? とは異なる) と @ の意味について、私は完全に漠然としていることを認めなければなりません。
このコードをどのように修正しますか?
そして最新の質問ですが、C++ で複合パターンがたまたま私にとって最も重要だったので、私もこれをやろうとしています。そして明らかに、Haskell では 1 ~ 2 行でほぼ記述できることがわかります (これは私にとって本当に驚くべきことです)。
しかし、コンポジションのリーフ コンストラクターとコンポジット コンストラクターがある種の同じインターフェイスを持つ可能性があるという事実を、どのように表現しますか? (データは可変ではないため、適切な言葉ではないことは承知していますが、私の懸念/目標を推測して理解していただければ幸いです)
これはコンパイル エラーの合計です。
src\Main.hs:27:79:
Couldn't match expected type `[r]'
against inferred type `Composition a'
In the expression: y
In the second argument of `map', namely `[y]'
In the expression: map g [y]
src\Main.hs:30:20:
Could not deduce (Ord a) from the context ()
arising from a use of `>' at src\Main.hs:30:20-24
Possible fix:
add (Ord a) to the context of the type signature for `maxOfPair'
In the expression: (x > y)
In the expression: if (x > y) then (x) else (y)
In the definition of `maxOfPair':
maxOfPair x y = if (x > y) then (x) else (y)
src\Main.hs:41:0:
Occurs check: cannot construct the infinite type: a = [a] -> [a]
When generalising the type(s) for `sumTree'
編集 したがって、これは非バイナリカタモルフィズムの最終バージョンです
data Composant a = Leaf a
| Composite [Composant a]
data CompositionAlgebra a r = CompositionAlgebra { leaf :: a → r
, composite :: [r] → r }
foldComposition :: CompositionAlgebra a r → Composant a → r
foldComposition a@(CompositionAlgebra {leaf = f}) (Leaf x) = f x
foldComposition a@(CompositionAlgebra {composite = g}) (Composite ys) = g(map(foldComposition a) ys)
maxOfPair :: Ord a ⇒ a → a → a
maxOfPair x y = if( x > y)
then (x)
else (y)
maxInList :: Ord a => [a] → a
maxInList (x:xs) = maxOfPair x (maxInList xs)
treeDepth :: CompositionAlgebra a Integer
treeDepth = CompositionAlgebra { leaf = const 1, composite = λx → 1 + maxInList x }
addList :: Num a ⇒ [a] → a
addList (x:xs) = x + addList xs
sumTree :: (Num a) ⇒ CompositionAlgebra a a
sumTree = CompositionAlgebra { leaf = id, composite = addList }
以下の有効な回答によると、C++ インターフェイス契約に相当する Haskell を求めていたのは、型クラスの制約のようです。
したがって、デザイン パターン Composite は、Composition a を構築するときに型クラスの制約を適用することによって実現されます。おそらく、新しい特殊なデータを定義する必要があります。しかし、それを行う前に型クラスを学ぶ必要があります:-)