На данный момент мечта все еще продолжается, в каждой концепции Haskell я узнаю, что я более заманчивый.
И все же я не полностью выполнил работу над ответом этого драгоценного @ luqui на мой предыдущий вопрос о катаморфизме , и я собираюсь вернуться к нему, пока все не будет в порядке. Это был пример кода в Википедии, посвященный катаморфизму на деревьях BINARY .
Тем не менее, я попытался реализовать катаморфизм для NIN 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]
- эта последняя строка не соответствует ghc на "map g [y]"
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 = (+) }
- и эта последняя сумма не подходит для ghc
Я вижу> и +, так же, как операторы C ++> и +. Так что я не понимаю, что ghc злится на меня, если я не даю этому объекту реализацию opertor> / + или нет.
Во-вторых, я должен признать, что совершенно не уверен в смысле => (отличается от -> ???) и @, который, похоже, напоминает руководство по сопоставлению с образцом.
Как бы вы исправили этот код?
И последний вопрос,
Я также пытаюсь сделать это, потому что Composite Pattern оказался самым важным для меня в C ++. И, очевидно, я вижу, что это почти можно описать только одной / двумя строками в Haskell (это действительно удивительно для меня).
Но как бы вы сказали людям, что Leaf и Composite конструктор Composition могут иметь один и тот же интерфейс? (Я знаю, что это нехорошее слово, поскольку данные не являются изменяемыми, но я надеюсь, что вы можете угадать - понять мою проблему / цель)
это общая ошибка компиляции;
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'
EDIT
Так что это окончательная версия для недвоичного катаморфизма
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 }
И в соответствии с действительным ответом ниже: то, что я просил для haskell-эквивалента контрактов C ++ Interfaces, похоже, является ограничениями классов типов.
Таким образом, шаблон проектирования Composite будет достигнут путем применения ограничений класса типов при создании Composition a. Возможно, новые специализированные данные должны быть определены. Но я должен выучить классы типов, прежде чем делать это: -)