我有一个非二叉树:
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)))
答案 0 :(得分:2)
我会回答您的问题并回答您的上一条评论:
我已移除弯曲支架并出错。如果您发布一些代码,我将非常感激。我的错误消息:无法将预期类型MultTree Int'与实际类型[MultTree a]'
匹配
此处的问题是您指定minBound :: Int
的类型。但是在你的函数类型中,你说你有a
的任何类型的树Ord
。
dataInterval:: (Ord a) => MultTree a -> MultTree a
因此,Int
不等于a
。如果您不希望您的树具有多态性,那么您可以只使用dataInterval :: MultTree Int -> MultTree Int
。
但这不是最好的解决方案。您可以将minBound
和maxBound
用于多态类型,但需要在类型签名中将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]]