返回具有非二叉树的函数的树

时间:2017-02-04 12:08:11

标签: haskell tree

我有一个非二叉树:

data MultTree b = DataNode b | IndexNode Int Int [MultTree b] deriving (Show)

注意DataNode's被视为leafs,IndexNode's被视为分支。

现在我尝试在IndexNode中实现这一点,将较小的Int值设置为子树的DataNode的最小值,并将较大的Int值设置为子树DataNode的最大值。

对于没有子树的IndexNode's,较小的Int值设置为minBound::Int,较大的值设置为maxBound::Int

到目前为止,这是我的功能:

dataInterval:: (Ord a) => MultTree a -> MultTree a
dataInterval (DataNode x) = (DataNode x)
dataInterval(IndexNode x y [])
      | x > y  = (IndexNode (maxBound :: Int) (minBound :: Int) [])
      | x < y  = (IndexNode (minBound :: Int) (maxBound :: Int) [])
      | x == y = (IndexNode x y [])
datenInterval (IndexNode x y subtrees)
      | x > y  = (IndexNode (maxValue subtrees) (minValue subtrees) (map (dataInterval subtrees)))
      | x < y  = (IndexNode (minValue subtrees) (maxValue subtrees) (map (dataInterval subtrees)))
      | x == y = (IndexNode x y (map (dataInterval subtrees)))

必须递归调用函数dataInterval

现在我不知道该怎么做,因为dataInterval需要一棵树但不知何故我必须调用完整列表。 dataInterval不允许这样做。

问题:如何通过使用列表中的子树递归调用dataInterval?那么subtrees列表的每个树都会被调用吗?

我认为它可能是某些功能,例如map,但返回子树而不是列表。

目前错误消息看起来像是:

  

无法匹配预期类型的​​MultTree a2                     实际类型[MultTree a]       *在datenIntervalle的第一个参数中,即子树         在map的第一个参数中,即(datenIntervalle子树)         在IndexNode的第三个参数中,即           (map(datenIntervalle子树))

示例树&amp;完整代码:

t2 :: MultTree Int
t2 = IndexNode 3 42 [IndexNode 7 8 [DataNode 3, DataNode 5, DataNode 7, DataNode 9], DataNode 6, IndexNode 10 23 [DataNode 99, DataNode 78, DataNode 24]]

dataList:: MultTree a -> [a]
dataList(DataNode x) = [x]
dataList(IndexNode _ _ subtress) = concat' (map dataList subtress)

maxValue :: (Ord a) => MultTree a -> a
maxValue tree = maximum (dataList tree)

minValue :: (Ord a) => MultTree a -> a
minValue tree = minimum (dataList tree)

dataInterval:: (Ord a) => MultTree a -> MultTree a
dataInterval(DataNode x) = (DataNode x)
dataInterval(IndexNode x y [])
      | x > y  = (IndexNode (maxBound :: Int) (minBound :: Int) [])
      | x < y  = (IndexNode (minBound :: Int) (maxBound :: Int) [])
      | x == y = (IndexNode x y [])
dataInterval(IndexNode x y subtrees)
      | x > y  = (IndexNode (maxValue subtrees) (minValue subtrees) (map (dataInterval subtrees)))
      | x < y  = (IndexNode (minValue subtrees) (maxValue subtrees) (map (dataInterval subtrees)))
      | x == y = (IndexNode x y (map (dataInterval subtrees)))

1 个答案:

答案 0 :(得分:2)

我会回答您的问题并回答您的上一条评论:

  

我已移除弯曲支架并出错。如果您发布一些代码,我将非常感激。我的错误消息:无法将预期类型MultTree Int'与实际类型[MultTree a]'

匹配

此处的问题是您指定minBound :: Int的类型。但是在你的函数类型中,你说你有a的任何类型的树Ord

dataInterval:: (Ord a) => MultTree a -> MultTree a

因此,Int不等于a。如果您不希望您的树具​​有多态性,那么您可以只使用dataInterval :: MultTree Int -> MultTree Int。 但这不是最好的解决方案。您可以将minBoundmaxBound用于多态类型,但需要在类型签名中将Bounded约束添加到a。而且您不需要在函数中指定minBound的类型,因为 Haskell 具有类型推断。所以这里是完整的工作示例(我还删除了一些(),因为 Haskell 不是 Lisp ):

data MultTree b = DataNode b | IndexNode b b [MultTree b] deriving (Show)

t2 :: MultTree Int
t2 = IndexNode 3 42 [ IndexNode 7 8 [ DataNode 3
                                     , DataNode 5
                                     , DataNode 7
                                     , DataNode 9
                                     ]
                    , DataNode 6
                    , IndexNode 10 23 [ DataNode 99
                                      , DataNode 78
                                      , DataNode 24
                                      ]
                    ]

dataList :: MultTree a -> [a]
dataList (DataNode x)             = [x]
dataList (IndexNode _ _ subtrees) = flattenSubtrees subtrees

flattenSubtrees :: [MultTree a] -> [a]
flattenSubtrees = concatMap dataList

maxValue :: Ord a => [MultTree a] -> a
maxValue trees = maximum (flattenSubtrees trees)

minValue :: Ord a => [MultTree a] -> a
minValue trees = minimum (flattenSubtrees trees)

dataInterval :: (Bounded a, Ord a) => MultTree a -> MultTree a
dataInterval (DataNode x) = DataNode x
dataInterval node@(IndexNode x y [])
      | x > y  = IndexNode maxBound minBound []
      | x < y  = IndexNode minBound maxBound []
      | x == y = node
dataInterval (IndexNode x y subtrees)
      | x > y  = IndexNode (maxValue subtrees) (minValue subtrees) mappedSubtrees
      | x < y  = IndexNode (minValue subtrees) (maxValue subtrees) mappedSubtrees
      | x == y = IndexNode x y mappedSubtrees
  where
    mappedSubtrees = map dataInterval subtrees

我想注意这个功能实现效率不高。因为每次需要评估最小值和最大值时遍历完整的树,而实际上只有在找到subtrees的结果后才能遍历最后一级。 t2上函数调用的结果是:

ghci> dataInterval t2 
IndexNode 3 99 [IndexNode 3 9 [DataNode 3,DataNode 5,DataNode 7,
DataNode 9],DataNode 6,IndexNode 24 99 [DataNode 99,DataNode 78,
DataNode 24]]