[英]Haskell - Translate a list to a recursive data structure
I found this problem in a Haskell textbook.我在 Haskell 教科书中发现了这个问题。 Given a recursive data structure:
给定递归数据结构:
data Foo = A Foo Foo | B Int Foo | C Int
create a function:创建一个函数:
createFooFromList :: [Int] -> Foo -> Foo
that takes in a list and a Foo
, applies the list to the Foo
, and returns the new Foo
.它接受一个列表和一个
Foo
,将该列表应用于Foo
,并返回新的Foo
。
What "applying" means is best described using an example.使用示例最好地描述“应用”的含义。
Say we have a Foo
that is defined as B 0 (B 1 (A (B 0 (C 1)) (B 1 (C 1))))
and we have to apply the list [0,0,1,0,2,0]
to this Foo
.说,我们有一个
Foo
被定义为B 0 (B 1 (A (B 0 (C 1)) (B 1 (C 1))))
我们必须应用列表[0,0,1,0,2,0]
到这个Foo
。 To do this, simply take each integer in the given sequence and replace integers in the Foo
structure in order with these integers in the sequence.为此,只需取给定序列中的每个整数,并按顺序用序列中的这些整数替换
Foo
结构中的整数。
So for the above example, our output would be B 0 (B 0 (A (B 1 (C 0)) (B 2 (C 0))))
所以对于上面的例子,我们的输出将是
B 0 (B 0 (A (B 1 (C 0)) (B 2 (C 0))))
So far, I have created a function that applies the list to the B
and C
structures.到目前为止,我已经创建了一个将列表应用于
B
和C
结构的函数。 C
is trivial, and B
is also easy as I simply set the head of the list to the Int
parameter of B
, and recursively apply the rest of the list to the Foo
part of B
. C
很简单,而B
也很简单,因为我只需将列表的头部设置为B
的Int
参数,然后递归地将列表的其余部分应用于B
的Foo
部分。 However I am unsure as to how to deal with A
.但是我不确定如何处理
A
。
Here is a hint:这是一个提示:
I would start by writing an auxiliary function, which takes the [Int]
and Foo
arguments, and returns not just the output Foo
but an additional [Int]
representing the numbers in the input list which have not been used, yet.我将首先编写一个辅助函数,它接受
[Int]
和Foo
参数,不仅返回输出Foo
,还返回一个额外的[Int]
表示输入列表中尚未使用的数字。 Hence, the resulting output type can be a pair.因此,结果输出类型可以是一对。
The intuition here is that this auxiliary function does not assume that the input [Int]
list contains the right amount of numbers for the Foo
input, but allows more Int
s to be present, and returns the ones in excess.这里的直觉是这个辅助函数不假设输入
[Int]
列表包含Foo
输入的正确数量的数字,而是允许存在更多的Int
,并返回多余的。
Using this auxiliary function, you can handle the A
case with two Foo
s inside: you call the auxiliary function on the first Foo
, and obtain the excess Int
s, then you use those for the second Foo
, and return the new excess Int
s.使用这个辅助函数,您可以处理内部有两个
Foo
的A
情况:您在第一个Foo
上调用辅助函数,并获得多余的Int
,然后将它们用于第二个Foo
,并返回新的多余Int
s .
(A more advanced approach would be to use a State [Int]
monad, but the above basic approach should be fine.) (更高级的方法是使用
State [Int]
monad,但上述基本方法应该没问题。)
As @chi wrote above, creating a helper function something like : 如@chi上面所述,创建一个类似于以下内容的辅助函数:
helper :: [Int] -> Foo -> (Foo, [Int])
that returns the "extra" ints will get you pretty far, and also avoid having to count elements. 返回“额外”整数的代码将使您走得更远,并且还避免了必须对元素进行计数。
I'm assuming that your main problem with the A case is in handing the extra integers from one Foo to there other? 我假设您与A案有关的主要问题是将多余的整数从一个Foo传递到另一个?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.