Reputation: 61
I am trying to design a Haskell program to build a game theory tree that creates a Game (capital G) by repeatedly playing a base game (small G) a specified number of times.
The foo function below works correctly by adding the outcome (or payoff) of one round to each of the outcomes/payoffs of the base game. One major limitation is that the base game is permanently set to have three outcomes.
The foo' function (which does not work) is supposed to be a generalization of the foo function. That is to mimic the foo function by using the map function and a list of values that represent the base game.
data MyTree a = Root a [MyTree a] | Branch a [MyTree a] | Leaf a | EmptyNode deriving Show
x1:: Integer
x1 = 1
x2 :: Integer
x2 = 25
x3 :: Integer
x3 = 100
foo :: [Integer] -> MyTree [Integer]
foo [r, a]
| r == 0 = Leaf [a]
| a == 0 = Root [a] [foo [r-1, a+x1], foo [r-1, a+x2], foo [r-1, a+x3]]
| otherwise = Branch [a] [foo [r-1, a+x1], foo [r-1, a+x2], foo [r-1, a+x3]]
lst = [x1, x2, x3]
foo' :: [Integer] -> MyTree [Integer]
foo' [r, a]
| r == 0 = Leaf [a]
| a == 0 = Root [a] map (foo'.(\y ->[r-1, y]).(\x -> a+x)) lst
| otherwise = Branch [a] map (foo'.(\y ->[r-1, y]).(\x -> a+x)) lst
The following errors show up twice (one for the a == 0 line and for the otherwise line). I list them only once since once I know how to fix an error, I can fix its duplicate.
The error messages I get are (a) and (b):
Couldn't match expected type ‘([Integer] -> MyTree [Integer]) -> [[Integer]] -> MyTree [Integer]’with actual type ‘MyTree [Integer]’
Couldn't match expected type ‘[MyTree [Integer]]’with actual type ‘(a0 -> b0) -> [a0] -> [b0]’
My question is this: How can I get the actual input to match the expected input? I've spent many days and hours working on the syntax and Google-searching for the solution.
Upvotes: 1
Views: 95
Reputation: 15045
The problem is just what the compiler says:
The function ‘Root’ is applied to four arguments, but its type ‘[Integer] -> [MyTree [Integer]] -> MyTree [Integer]’ has only two
That's because compiler assumes that [a]
, map
, (foo'.(\y ->[r-1, y]).(\x -> a+x))
and lst
are four separate arguments to function Root
.
It can be fixed either by using $
, which sets the priority of evaluation
foo' :: [Integer] -> MyTree [Integer]
foo' [r, a]
| r == 0 = Leaf [a]
| a == 0 = Root [a] $ map (foo'.(\y ->[r-1, y]).(\x -> a+x)) lst
| otherwise = Branch [a] $ map (foo'.(\y ->[r-1, y]).(\x -> a+x)) lst
Or, since it can be moved into a separate function (probably genList
name is not appropriate, certainly you can make up a better one):
foo' :: [Integer] -> MyTree [Integer]
foo' [r, a]
| r == 0 = Leaf [a]
| a == 0 = Root [a] genList
| otherwise = Branch [a] genList
where genList = map (foo'.(\y ->[r-1, y]).(\x -> a+x)) lst
Upvotes: 2