Haskell-树的前序编号
我正在准备非程序语言的考试。我有一个测试任务的例子,我不知道如何解决它 任务如下: 给定两个树结构:Haskell-树的前序编号,haskell,preorder,Haskell,Preorder,我正在准备非程序语言的考试。我有一个测试任务的例子,我不知道如何解决它 任务如下: 给定两个树结构: data Tree a = Nil1 | Node1 a [Tree a] data NumTree a = Nil2 | Node2 (a,Int) [NumTree a] 写函数 numberTree :: Num a => Tree a -> NumTree a 它将在预订单中返回编号的NumTree a 我试过了,但不知道如何继续 numberTree tree = n
data Tree a = Nil1 | Node1 a [Tree a]
data NumTree a = Nil2 | Node2 (a,Int) [NumTree a]
写函数
numberTree :: Num a => Tree a -> NumTree a
它将在预订单中返回编号的NumTree a
我试过了,但不知道如何继续
numberTree tree = numberTree' tree 1
numberTree' :: Num a => Tree a -> Int -> NumTree a
numberTree' Nil1 _ = Nil2
numberTree' (Node1 num list) x = (Node2 (num,x) (myMap x numberTree list))
我不知道如何编写这样的myMap
,因为它应该返回树和累计的预订单号,但我不知道如何做到这一点
欢迎您提出任何建议。您可以在此处使用:
mapAccumL
函数的行为类似于map
和foldl
的组合;它将一个函数应用于列表的每个元素,从左到右传递一个累加参数,并将此累加器的最终值与新列表一起返回
查看类型,尝试连接匹配的导线,然后主功能看起来像
import Data.List (mapAccumL)
data Tree a = Nil1 | Node1 a [Tree a] deriving Show
data NumTree a = Nil2 | Node2 (a,Int) [NumTree a] deriving Show
numberTree :: Tree a -> NumTree a
numberTree tree = tree2
where
(_, [tree2]) = mapAccumL g 1 [tree]
g n Nil1 = (n, Nil2)
g n (Node1 x trees) = (z, Node2 (x,n) trees2)
where
(z, trees2) = ....
mapAccumL g(n+1)树
不需要numa=>
约束。您不访问节点的值,只需对节点进行计数,而不管它们携带什么:
>数字树(节点11.1[节点12.2[节点13.3[],无1],节点14.4[])Node2(1.1,1)[Node2(2.2,2)[Node2(3.3,3)[],Nil2],Node2(4.4,4)[]
这是对
状态
monad的一个很好的使用,它负责通过访问每个节点的递归调用对用于给每个节点编号的值进行线程化
import Control.Monad
import Control.Monad.State
data Tree a = Nil1 | Node1 a [Tree a] deriving (Show)
data NumTree a = Nil2 | Node2 (a,Int) [NumTree a] deriving (Show)
numberTree :: Tree a -> NumTree a
numberTree Nil1 = Nil2
numberTree tree = evalState (numberTree' tree) 0
-- The state stores the value used to number the root
-- of the current tree. Fetch it with get, and put back
-- the number to use for the next root.
-- numberTree' is then used to number each child tree
-- in order before returning a new NumTree value.
numberTree' :: Tree a -> State Int (NumTree a)
numberTree' Nil1 = return Nil2
numberTree' (Node1 root children) = do rootNum <- get
put (rootNum + 1)
newChildren <- mapM numberTree' children
return (Node2 (root, rootNum) newChildren)
import-Control.Monad
进口控制单体状态
数据树a=Nil1 |节点1A[树a]派生(显示)
数据NumTree a=Nil2 | Node2(a,Int)[NumTree a]派生(Show)
numberTree::树a->NumTree a
numberTree Nil1=Nil2
numberTree树=evalState(numberTree树)0
--状态存储用于对根进行编号的值
--当前树的。用get把它拿来,然后放回去
--用于下一个根的数字。
--然后使用numberTree对每个子树进行编号
--在返回新的NumTree值之前按顺序排序。
numberTree':树a->State Int(NumTree a)
numberTree'Nil1=返回Nil2
numberTree'(Node1 root children)=do rootNum我不明白为什么需要Num a
约束。我认为您的助手函数应该具有类型numberTree'::Tree a->Int->(NumTree a,Int)
。谢谢,但我认为它是numberTree'::Tree a->Int->NumTree a
或者不是?而且Num a
是因为树中是Num。你的numberTree
函数不应该关心树元素,它应该只添加数字。非常感谢你的解决方案。它似乎在工作,但在我的ghci中不是状态
monad。它是如何实现的?@Vojacejo try