List Haskell:从列表中构建一棵树

List Haskell:从列表中构建一棵树,list,haskell,tree,higher-order-functions,List,Haskell,Tree,Higher Order Functions,考虑以下类型: data LTree a = Leaf a | Fork (LTree a) (LTree a) 现在考虑下列函数,列出树的叶子,以及其深度 tolistdepth :: LTree a -> [(a,Int)] tolistdepth (Leaf x) = [(x,0)] tolistdepth (Fork e d) = map (\(x,n) -> (x,n+1)) (tolistdepth e ++ tolistdepth d) 我需要定义以下函数的帮助 b

考虑以下类型:

data LTree a = Leaf a | Fork (LTree a) (LTree a)

现在考虑下列函数,列出树的叶子,以及其深度

tolistdepth :: LTree a -> [(a,Int)]
tolistdepth (Leaf x) = [(x,0)]
tolistdepth (Fork e d) = map (\(x,n) -> (x,n+1)) (tolistdepth e ++ tolistdepth d)
我需要定义以下函数的帮助

build :: [(a, Int)] -> LTree a
计算第一个函数的倒数,这样

build (tolistdepth a) = a
我甚至不知道从哪里开始:)


我已设法做到以下几点:

build :: [(a, Int)] -> LTree a
build xs = let ys= map (\(x, n) -> (Leaf x, n)) xs
           in SOMETHING iterateUntil SOMETHING (buildAssist ys)

buildAssist :: [(LTree a, Int)] -> [(LTree a, Int)]
buildAssist [] = []
buildAssist [x] = [x]
buildAssist (x@(t1, n1):y@(t2, n2):xs) = if n1 == n2 then ((Fork t1 t2), n1 - 1):buildAssist xs
                                                     else x:(buildAssist (y:xs))
这样的话,我想我已经处理好了什么时候分叉。 现在,我如何在我的原始函数中使用buildAssist(如果buildAssist当然有用的话)


我相信我已经弄明白了

请让我知道这是否有效:

build :: [(a,Int)] -> LTree a
build l = fst (buildaccum 0 l)

buildaccum :: Int -> [(a,Int)] -> (LTree a, [(a,Int)])
buildaccum n l@((a,b):t) |n==b = (Leaf a,t)
                         |n<b = (Fork e d, l2)
     where (e,l1) = buildaccum (n+1) l
           (d,l2) = buildaccum (n+2) l1
build::[(a,Int)]->LTree a
build l=fst(buildaccum 0 l)
buildaccum::Int->[(a,Int)]->(LTree a,[(a,Int)])
buildaccum n l@((a,b):t)|n==b=(叶a,t)

|n我将给您一个提示,演示解析列表时的一种有用技术

这里真正起作用的是这样一个函数:

build' :: [(a,Int)] -> (LTree a, [(a,Int)])
build' [] = error "oops - bad input list"
build' ((a,n):xs) =
  if we are at a leaf node, return (LTree a, xs)
  if we decide we need to fork, then return (Fork e f,zs)
    where
      (e,ys) = build' ((a,n):xs)  -- parse the left branch
      (f,zs) = build' ys          -- parse the right branch
也就是说,
build'
返回一个
ltreea
和它尚未使用的输入列表的其余部分

在这种形式下,
build'
的定义如下:

build' :: [(a,Int)] -> (LTree a, [(a,Int)])
build' [] = error "oops - bad input list"
build' ((a,n):xs) =
  if we are at a leaf node, return (LTree a, xs)
  if we decide we need to fork, then return (Fork e f,zs)
    where
      (e,ys) = build' ((a,n):xs)  -- parse the left branch
      (f,zs) = build' ys          -- parse the right branch
请注意,这只是伪代码,还有一些重要的细节缺失,我将作为练习留下

有趣的部分是如何在
Fork
案例中确定剩余的输入列表。
ys
是解析左分支后的剩余输入,它作为输入馈送到
build'
,以获得右分支,调用
build'
zs
)的剩余输入作为原始
build'
调用的剩余输入返回

更新:

要使用起始值
x
迭代函数
f
,直到某个条件
p
,请遵循以下公式:

iterateUntil p f x = if p x then x else iterateUntil p f (f x)

我将给您一个提示,演示解析列表时的一种有用技术

这里真正起作用的是这样一个函数:

build' :: [(a,Int)] -> (LTree a, [(a,Int)])
build' [] = error "oops - bad input list"
build' ((a,n):xs) =
  if we are at a leaf node, return (LTree a, xs)
  if we decide we need to fork, then return (Fork e f,zs)
    where
      (e,ys) = build' ((a,n):xs)  -- parse the left branch
      (f,zs) = build' ys          -- parse the right branch
也就是说,
build'
返回一个
ltreea
和它尚未使用的输入列表的其余部分

在这种形式下,
build'
的定义如下:

build' :: [(a,Int)] -> (LTree a, [(a,Int)])
build' [] = error "oops - bad input list"
build' ((a,n):xs) =
  if we are at a leaf node, return (LTree a, xs)
  if we decide we need to fork, then return (Fork e f,zs)
    where
      (e,ys) = build' ((a,n):xs)  -- parse the left branch
      (f,zs) = build' ys          -- parse the right branch
请注意,这只是伪代码,还有一些重要的细节缺失,我将作为练习留下

有趣的部分是如何在
Fork
案例中确定剩余的输入列表。
ys
是解析左分支后的剩余输入,它作为输入馈送到
build'
,以获得右分支,调用
build'
zs
)的剩余输入作为原始
build'
调用的剩余输入返回

更新:

要使用起始值
x
迭代函数
f
,直到某个条件
p
,请遵循以下公式:

iterateUntil p f x = if p x then x else iterateUntil p f (f x)

关于要构建的参数,您可以假设什么?并非所有可能的输入都可以生成树。@ChrisTaylor假设输入可以生成树。谢谢你指出它。如果你一直调用它直到找到一个元素,我想你可以使用你的
buildAssist
。@user5402你能详细说明一下我是如何做到的吗?我更新了我的答案。一旦你的方法奏效,我会发布我所想的解决方案。你能对要构建的论点做出什么假设?并非所有可能的输入都可以生成树。@ChrisTaylor假设输入可以生成树。谢谢你指出它。如果你一直调用它直到找到一个元素,我想你可以使用你的
buildAssist
。@user5402你能详细说明一下我是如何做到的吗?我更新了我的答案。一旦你的方法成功了,我会发布我想的解决方案。谢谢。这给了我一个想法。我用我提出的内容编辑了我的问题。请同时提供您的解决方案。我总是喜欢看到同一个问题的不同解决方案,这对我学习这门语言有很大帮助。好的,这是一个有用的函数。关于手头的问题,我不知道何时停止迭代(例如,我不知道在上面的定义中我的p应该是什么)。谢谢。这给了我一个想法。我用我提出的内容编辑了我的问题。请同时提供您的解决方案。我总是喜欢看到同一个问题的不同解决方案,这对我学习这门语言有很大帮助。好的,这是一个有用的函数。关于手头的问题,我不知道何时停止迭代(例如,我不知道在上面的定义中我的p应该是什么)。