Sajid Anower
Sajid Anower

Reputation: 171

Gen for a custom data type in Haskell

I was trying to make a truth table for a list of strings. Say, I have a list ["a","b"] and as an output, I want [[("a",True),("b",True)], [("a",True),("b",False)], [("a",False),("b",True)], [("a",False),("b",False)]]

Each of those instances in the truth table are a custom data type defined as

data TableRow = [(String,Bool)]

Is there any easier way of doing this? Until now I have been doing this


genRow :: [String] -> [TableRow]
genRow [] = []
genRow (x:xs) = ((makeRow x True) : genRow xs) ++ 
            ((makeRow x False) : genRow xs)

Quite obviously, this does not quite give me what I expect. Note that makeRow just takes in a String and a Bool and returns a TableRow.

Is there any cleaner way of doing this? Thanks

Upvotes: 1

Views: 442

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477437

The problem with your program is that genRow :: [String] -> [TableRow] generates a list of TableRow elements, and you cannot use the cons (:) constructor on a (String,Bool) and TableRow since TableRow is [[(String,Bool)]].

You can however easily use list comprehension for that:

genRow :: [String] -> [[(String,Bool)]]
genRow [] = [[]]
genRow (x:xs) = [(x,b):ti | b <- [True,False], ti <- ts]
    where ts = genRow xs

The first statement should thus generate a list with one element: the empty list [] (not the empty list as result). Furthermore we use list comprehension: we iterate over the two Bools True and False for b and for each such value, we iterate over the possible values as tails ts and prepend the (x,b) to each of the possible tails.

This gives:

*Main> genRow ["A","B","C"]
[[("A",True),("B",True),("C",True)],
 [("A",True),("B",True),("C",False)],
 [("A",True),("B",False),("C",True)],
 [("A",True),("B",False),("C",False)],
 [("A",False),("B",True),("C",True)],
 [("A",False),("B",True),("C",False)],
 [("A",False),("B",False),("C",True)],
 [("A",False),("B",False),("C",False)]]
*Main> genRow ["Foo","Bar"]
[[("Foo",True),("Bar",True)],
 [("Foo",True),("Bar",False)],
 [("Foo",False),("Bar",True)],
 [("Foo",False),("Bar",False)]]

(new lines added for readability)

Upvotes: 1

Related Questions