Reputation: 13
I found this problem in a Haskell textbook. 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
.
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
. 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.
So for the above example, our output would be 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. 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
. However I am unsure as to how to deal with A
.
Upvotes: 1
Views: 215
Reputation: 116139
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.
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.
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.
(A more advanced approach would be to use a State [Int]
monad, but the above basic approach should be fine.)
Upvotes: 2