我的KdTree的派生可折叠实例出了什么问题?

时间:2016-07-23 16:57:50

标签: haskell

我正在尝试为我的KdTree数据结构派生一个可折叠的实例。当我尝试创建toList函数时,问题就出现了。

toList :: KdTree BBox3 a -> [(BBox3,a)]
toList t = F.foldr (:) [] t

在尝试编译时,我收到了此错误

Couldn't match type ‘a’ with ‘(BBox3, a)’
  ‘a’ is a rigid type variable bound by
      the type signature for toList :: KdTree BBox3 a -> [(BBox3, a)]
      at Data/Trees/KdTree/Regions/KThree/KThreeTree.hs:127:13
Expected type: KdTree BBox3 (BBox3, a)
  Actual type: KdTree BBox3 a
Relevant bindings include
  t :: KdTree BBox3 a
    (bound at Data/Trees/KdTree/Regions/KThree/KThreeTree.hs:128:10)
  toList :: KdTree BBox3 a -> [(BBox3, a)]
    (bound at Data/Trees/KdTree/Regions/KThree/KThreeTree.hs:128:3)
In the third argument of ‘foldr’, namely ‘t’
In the expression: foldr (:) [] t

我认为这是因为可折叠实例没有正确派生,所以我做了一个尖峰以查看正在生成的代码。 但事情就是这样,我的穗工作了。我添加了toList功能,没有任何抱怨,我无法弄清楚是什么造成了不同。所以,最终, 我将非常感谢如何为我的KdTree BBox a编写可折叠信息,或者对我的代码中出现问题的一些见解与我的峰值中的正确(但看似相同)代码进行比较。

下面是尖峰,以及我项目代码的链接。

{-# LANGUAGE TypeFamilies, InstanceSigs, DeriveFoldable, DeriveFunctor #-}

import Data.List
import qualified Data.Foldable as F

data BBox3 = BBox3 {
   v3x :: Double
 , v3y :: Double
 , v3z :: Double 
}

data AxisX = AxisX
data AxisY = AxisY
data AxisZ = AxisZ

class ( Bounded bbox) => KdTreeRegional bbox where

  data Axes bbox :: *
  data KdTree bbox :: * -> *
  data Leaf bbox :: * -> *

  toList :: KdTree bbox a -> [(bbox,a)]

instance KdTreeRegional BBox3 where
  data Axes BBox3 = X AxisX | Y AxisY | Z AxisZ

  data KdTree BBox3 a
    = KdNode {
        kdLeft     :: KdTree BBox3 a
      , nodeBBox   :: BBox3
      , kdSplit    :: (Axes BBox3,Double)
      , overlapped :: [(BBox3, a)]
      , kdRight    :: KdTree BBox3 a
      }
    | KdLeaf (Maybe (Leaf BBox3 a))
    deriving (F.Foldable)

  data Leaf BBox3 a = Leaf {
         leafBBox :: BBox3
       , kdleaf   :: [(BBox3,a)]
       } deriving (F.Foldable)

  toList :: KdTree BBox3 a -> [(BBox3,a)]
  toList t = F.foldr (:) [] t

https://github.com/mlitchard/kdtree/blob/stack/Data/Trees/KdTree/Regions/Internal.hs

https://github.com/mlitchard/kdtree/blob/stack/Data/Trees/KdTree/Regions/KThree/KThreeTree.hs

更新:这不编译。我收到了这个错误

 The IO action ‘main’ is not defined in module ‘Main’

我将其解释为Warning,并被忽略。我添加了main = undefined并收到了我一直以来遇到的同样错误。

2 个答案:

答案 0 :(得分:3)

foldr聚合可折叠结构的最右侧类型参数。

class Foldable t where
    foldr :: (a -> b -> b) -> b -> t a -> b
    -- ...

在这种情况下,t ~ KdTree BBox3。您toList的实施将生成a s。

列表
toList :: KdTree BBox3 a -> [a]
toList t = F.foldr (:) [] t

(顺便说一下,这个确切的函数已存在于Data.Foldable模块中。)

鉴于您设置系统的方式,KdTree作为关联类型,无法使用Foldable(甚至Bifoldable)机制来提取{{ 1}}来自BBox3。你的代码看起来比它应该更复杂 - 你到底想要实现什么?

答案 1 :(得分:1)

  

所以,最后,我很感激如何为我的KdTree BBox a

写一个可折叠的线索。

toList函数看起来应该是:

toList :: KdTree BBox3 a -> [(BBox3,a)]
toList (KdLeaf Nothing) = []
toList (KdLeaf (Just leaf)) = kdleaf leaf
toList (KdNode node) = toList (kdLeft node) ++ toList (kdRight node) ++ overlapped node

并且foldr是:

foldr :: (a -> b -> b) -> b -> KdTree BBox3 a -> b
foldr f z kdtree = foldr f z (toList kdtree)