[英]Haskell monoid foldable rose tree
I need to make a foldable instance for a Rose tree data structure: 我需要为Rose树数据结构创建一个可折叠的实例:
data Rose a = a :> [Rose a]
deriving (Eq, Show)
With the following monoid and rose-related class/instances: 使用以下monoid和rose相关的类/实例:
instance Functor Rose where
fmap f (a :> bs) = (f a) :> (map (fmap f) bs)
class Monoid a where
mempty :: a
(<>) :: a -> a -> a
instance Monoid [a] where
mempty = []
(<>) = (++)
What I tried: 我尝试了什么:
instance Foldable Rose where
fold (a:>b) = a <> (foldMap fold b)
However this is not working properly, for the system check I get the error: 但是这不能正常工作,对于系统检查我得到错误:
*** Failed! Exception: 'Prelude.undefined':
[] :> []
But I'm not sure why it doesn't work, could anyone help me out? 但我不确定为什么它不起作用,任何人都可以帮助我吗?
Thanks in advance! 提前致谢!
Best Regards, Skyfe. 最诚挚的问候,Skyfe。
Your implementation of fold
was correct, there is no reason to change it. 你的
fold
实现是正确的,没有理由改变它。
The problem is that fold
isn't sufficient to define Foldable
. 问题是
fold
不足以定义Foldable
。 From the documentation : 从文档 :
class Foldable t where Source
Data structures that can be folded.
可以折叠的数据结构。
Minimal complete definition:
foldMap
orfoldr
.最小完整定义:
foldMap
或foldr
。
So you must define either foldMap
or foldr
(or both). 因此,您必须定义
foldMap
或foldr
(或两者)。 Defining foldMap
is easier and more natural (and also more effective in many cases). 定义
foldMap
更容易,更自然(在许多情况下也更有效)。 So you should write something like: 所以你应该这样写:
import Data.Foldable
import Data.Monoid
data Rose a = a :> [Rose a]
deriving (Eq, Show)
instance Foldable Rose where
foldMap f (x :> xs) = f x <> foldMap (foldMap f) xs
This is only tangentially related, but if you realize that Rose Trees are the same as Cofree []
from Control.Comonad.Cofree
, then you can get a Foldable
instance "for free" from the foldable instance of []
like so: 这仅仅是切向相关的,但是如果你认识到玫瑰树是一样
Cofree []
从Control.Comonad.Cofree
,那么你就可以得到一个Foldable
的的可折叠实例的实例“免费” []
像这样:
import Control.Comonad.Cofree
import Data.Foldable as F
type RoseTree = Cofree []
Load it up into GHCi: 加载到GHCi中:
λ> let tree = 1 :< [1 :< [], 2 :< [], 3 :< []] :: RoseTree Int
λ> :t F.foldr (+) 0 tree
F.foldr (+) 0 tree :: Int
λ> F.foldr (+) 0 tree
7
You can also just derive Foldable
, or write your own implementation (like you've done). 您也可以只获得
Foldable
,或编写自己的实现(就像您已经完成的那样)。
It seems like I found the answer to my own question. 好像我找到了自己问题的答案。
Solution: 解:
instance Foldable Rose where
fold (a:>b) = a <> (foldr (<>) mempty (map fold b))
Had to first append each of the elements in the list with the head element (and do the same for each of the bound elements to those rose trees), then fold the list together with an non-adjusting element mempty. 必须首先使用head元素追加列表中的每个元素(并对每个玫瑰树的绑定元素执行相同的操作),然后将列表与非调整元素mempty一起折叠。
Although OP says he/she has found the answer, the solution lacks the base case: 虽然OP说他/她找到了答案,但解决方案缺乏基本情况:
instance Foldable Rose where
fold (a:>[]) = a <> mempty
fold (a:>b) = a <> (foldr (<>) mempty (map fold b))
Otherwise an expection about non-exhaustive patterns in function fold will be thrown. 否则,将抛出关于函数折叠中的非穷举模式的预期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.