【问题标题】:Haskell monoid foldable rose treeHaskell 单体可折叠玫瑰树
【发布时间】:2014-10-08 12:52:01
【问题描述】:

我需要为玫瑰树数据结构创建一个可折叠的实例:

data Rose a = a :> [Rose a]
    deriving (Eq, Show)

使用以下幺半群和玫瑰相关的类/实例:

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 = []
    (<>)   = (++)

我尝试了什么:

instance Foldable Rose where
    fold (a:>b) =  a <> (foldMap fold b)

但是这不能正常工作,对于系统检查我得到了错误:

*** Failed! Exception: 'Prelude.undefined': 
[] :> []

但我不确定为什么它不起作用,有人可以帮我吗?

提前致谢!

最好的问候, Skyfe。

【问题讨论】:

  • 与其更新问题中的解决方案,不如把它写在这里作为答案?
  • 不错,没想到这种可能性!
  • deriving (Foldable){- LANGUAGE DeriveFoldable -} 怎么样?
  • 您可能需要查看 containers 包中的 Data.Tree,它是 Haskell 平台的一部分,也随 GHC 一起提供。

标签: class haskell monoids


【解决方案1】:

您对fold 的实现是正确的,没有理由更改它。

问题在于fold 不足以定义Foldable。来自the documentation

class Foldable t where Source

可以折叠的数据结构。

最小完整定义:foldMapfoldr

因此,您必须定义 foldMapfoldr(或两者)。定义foldMap 更容易、更自然(在许多情况下也更有效)。所以你应该写这样的东西:

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

【讨论】:

    【解决方案2】:

    这只是切线相关,但如果您意识到玫瑰树与Control.Comonad.Cofree 中的Cofree [] 相同,那么您可以从[] 的可折叠实例中“免费”获得Foldable 实例,例如所以:

    import Control.Comonad.Cofree
    import Data.Foldable as F
    
    type RoseTree = Cofree []
    

    将其加载到 GHCi:

    λ> let tree = 1 :< [1 :< [], 2 :< [], 3 :< []] :: RoseTree Int
    λ> :t F.foldr (+) 0 tree
    F.foldr (+) 0 tree :: Int
    λ> F.foldr (+) 0 tree
    7
    

    您也可以只派生Foldable,或编写自己的实现(就像您所做的那样)。

    【讨论】:

      【解决方案3】:

      似乎我找到了自己问题的答案。

      解决方案:

      instance Foldable Rose where
          fold (a:>b) =  a <> (foldr (<>) mempty (map fold b))
      

      必须首先将列表中的每个元素附加到头元素(并对每个绑定到玫瑰树的元素执行相同操作),然后将列表与非调整元素 mempty 折叠在一起。

      【讨论】:

        【解决方案4】:

        虽然 OP 说他/她找到了答案,但解决方案缺乏基本情况:

        instance Foldable Rose where
            fold (a:>[]) = a <> mempty
            fold (a:>b) =  a <> (foldr (<>) mempty (map fold b))
        

        否则将抛出函数折叠中非穷举模式的期望。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-21
          • 1970-01-01
          • 2014-07-24
          • 2012-06-07
          • 1970-01-01
          • 2015-10-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多