Design patterns 非二叉树与复合设计模式的类同构的初学者实现
就目前而言,梦想还在继续,在哈斯凯尔的每一个概念中,我都被吸引住了。 然而,我还没有完全完成这个宝贵的@luqui的答案,我会回来,直到它的好。这是关于维基百科上的示例代码,处理的是 尽管如此,我还是尝试对非二叉树实现了自同构,但我遇到了一些问题:Design patterns 非二叉树与复合设计模式的类同构的初学者实现,design-patterns,haskell,composite,catamorphism,Design Patterns,Haskell,Composite,Catamorphism,就目前而言,梦想还在继续,在哈斯凯尔的每一个概念中,我都被吸引住了。 然而,我还没有完全完成这个宝贵的@luqui的答案,我会回来,直到它的好。这是关于维基百科上的示例代码,处理的是 尽管如此,我还是尝试对非二叉树实现了自同构,但我遇到了一些问题: data Composition a = Leaf a | Composite [Composition a] data CompositionAlgebra a r = CompositionAlgebra
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]
-地图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 = (+) }
-对于ghc来说,这棵最迟的树也是错误的
<>我看到>和+,就像C++运算符>和+一样。因此,我不明白ghc在没有我的帮助下会对我生气,不管我是不是执行了Operator>/+操作
第二,我必须承认我对=>与->的区别完全不清楚???和@似乎是模式匹配的指南
如何更正此代码
还有一个最新的问题,
我也尝试这样做,因为复合模式恰好是我在C++中最重要的。很明显,在哈斯克尔的书中,只有一两行文字可以描述这一点,这对我来说真是太神奇了
但是,haskell的人如何表达这样一个事实:组合的Leaf和Composite构造函数可能具有某种相同的接口?我知道这不是一个好词,因为数据是不可变的,但我希望你能猜出我的担忧/目标
这是全部编译错误
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 }
并根据下面的有效答案:我所要求的Haskell等价的C++接口契约似乎是类型约束。
因此,设计模式组合将通过在构造组合a时应用类型类约束来实现。也许应该定义一个新的专用数据。但是我应该先学习TypeClass,然后再做:-这里有一些不同的错误,所以我不确定处理这些错误的最佳方法,但到底是什么 将来,尝试包含GHC提供的更多错误 在: 我可以看到foldCompose函数有两个错误,类型检查器只会捕获其中一个错误 您正在复合[y]上进行模式匹配,它将只匹配一个元素的列表。您可能需要复合ys,它将ys绑定到整个列表 map g[y]不会通过类型检查器,因为您已经将g定义为接受r的列表,但是您给了它一个a的列表 为了将a转换为r,您需要对其应用合成文胸:g映射折叠合成a ys 因此,我将这样写:
foldComposition :: CompositionAlgebra a r → Composition a → r
foldComposition a@(CompositionAlgebra {leaf = f}) (Leaf x ) = f x
foldComposition a@(CompositionAlgebra {composite = g}) (Composite ys) = g (map (foldComposition a) ys)
对于下一个错误:
maxOfPair :: a → a → a
maxOfPair x y = if( x > y) -- this doesnt please ghc either, Ordering trouble
then (x)
else (y)
在Haskell中,调用方可以根据自己的选择,使用任何类型来填充类型变量,如a here all by it lonesome
这意味着您在类型签名中声明函数maxPair将适用于每种输入类型。GHC以自己的方式抱怨操作符>不适用于每种类型,因此拒绝编译您的程序
您需要使用TypeClass来解决此问题。在Haskell中,类型类允许调用者选择要使用的类型,但有一些限制。我建议你读一本哈斯克尔的书
正确的类型签名应为:
maxOfPair :: Ord a => a → a → a
将Ord约束应用于类型a
另外,您应该使用标准函数。这里有一些不同的错误,因此我不确定在这样的情况下处理它的最佳方法,但究竟是什么 将来,尝试包含GHC提供的更多错误 在: 我可以看到foldCompose函数有两个错误,类型检查器只会捕获其中一个错误 您正在复合[y]上进行模式匹配,它将只匹配一个元素的列表。您可能需要复合ys,它将ys绑定到整个列表 map g[y]不会通过类型检查器,因为您已经将g定义为接受r的列表,但是您给了它一个a的列表 为了将a转换为r,您需要对其应用合成文胸:g映射折叠合成a ys 因此,我将这样写:
foldComposition :: CompositionAlgebra a r → Composition a → r
foldComposition a@(CompositionAlgebra {leaf = f}) (Leaf x ) = f x
foldComposition a@(CompositionAlgebra {composite = g}) (Composite ys) = g (map (foldComposition a) ys)
对于下一个错误:
maxOfPair :: a → a → a
maxOfPair x y = if( x > y) -- this doesnt please ghc either, Ordering trouble
then (x)
else (y)
在Haskell中,调用方可以根据自己的选择,使用任何类型来填充类型变量,如a here all by it lonesome
这意味着您在类型签名中声明函数maxPair将适用于每种输入类型。GHC以自己的方式抱怨操作符>不适用于每种类型,因此拒绝编译您的程序
您需要使用TypeClass来解决此问题。在Haskell中,类型类允许调用者选择要使用的类型,但有一些限制。我建议你读一本哈斯克尔的书
正确的类型签名应为:
maxOfPair :: Ord a => a → a → a
将Ord约束应用于类型a
另外,您应该使用标准函数
老实说,我必须承认我完全错了
模糊的感觉=>不同
从->开始???和@似乎是
就像模式匹配的指南
考虑函数,该函数测试列表是否包含某个值。你可以把它定义为
elem _ [] = False
elem x (y:ys) | x == y = True
| otherwise = elem x ys
哪个签名具有此功能?看起来像elem::a->[a]->Bool。但是编译器会抱怨,因为您编写了x==y,并且并不是为每个a定义了==函数,而是只为中的a定义了==函数。所以你需要为等式中的所有a指定类似的东西。。。。正是为了这个,你需要=>。因此elem的正确签名是elem::Eq a=>a->[a]->Bool
@使您可以为整个结构命名,同时在其上进行模式匹配。例如,如果你有这个图案a@x:xs用[1,2,3,4]调用该函数,那么a是[1,2,3,4],xis1和xs是[2,3,4]
第二,我必须承认我完全错了
模糊的感觉=>不同
从->开始???和@似乎是
就像模式匹配的指南
考虑函数,该函数测试列表是否包含某个值。你可以把它定义为
elem _ [] = False
elem x (y:ys) | x == y = True
| otherwise = elem x ys
哪个签名具有此功能?看起来像elem::a->[a]->Bool。但是编译器会抱怨,因为您编写了x==y,并且并不是为每个a定义了==函数,而是只为中的a定义了==函数。所以你需要为等式中的所有a指定类似的东西。。。。正是为了这个,你需要=>。因此elem的正确签名是elem::Eq a=>a->[a]->Bool
@使您可以为整个结构命名,同时在其上进行模式匹配。例如,如果你有这个图案a@x:xs用[1,2,3,4]调用该函数,那么a是[1,2,3,4],xis1和xs是[2,3,4]。Thanx Antoine。抱歉,如果我的帖子太长,但与你认为的相反,整个ghc的错误报告被引用在我的答案的底部。你花时间纠正我,真是太好了,我现在就去做。很高兴我能帮上忙!我希望我的回答不是太严厉——有时我发现很难找到正确的语气。不,别担心,我也不喜欢当编译错误没有出现在问题帖子中时;-。你指给我看的有趣的教程又是一个thanx。它在演示中非常轻量级,但我可以非常快速地投入其中,并专注于我感兴趣的要点。今天下午我要攻击IO和monads。我不耐烦了!安托万。抱歉,如果我的帖子太长,但与你认为的相反,整个ghc的错误报告被引用在我的答案的底部。你花时间纠正我,真是太好了,我现在就去做。很高兴我能帮上忙!我希望我的回答不是太严厉——有时我发现很难找到正确的语气。不,别担心,我也不喜欢当编译错误没有出现在问题帖子中时;-。你指给我看的有趣的教程又是一个thanx。它在演示中非常轻量级,但我可以非常快速地投入其中,并专注于我感兴趣的要点。今天下午我要攻击IO和monads。我不耐烦了!谢谢。现在我的口袋里有了=>和@;-。很好。所以,这意味着第一个a@是无用的,因为它不在该定义中使用。@Stephane:是的,你不需要它。Thx。现在我的口袋里有了=>和@;-。很好。这意味着第一个a@是无用的,因为它没有在那个定义中使用。@Stephane:是的,你不需要它。