问题
Given the following:
type Name = String
envs :: [Name] -> [[(Name , Bool)]]
I have to implement 'envs' so that given a list of Names, it returns all possible combinations of Names and booleans
My attempt didn't return all possible combinations, this was my code:
envs xxs@(x:xs) = [[ (name, value) | name <- xxs , value <- [False, True] ]]
the expected results for
envs ["P", "Q"]
are:
[ [ ("P",False)
, ("Q",False)
]
, [ ("P",False)
, ("Q",True)
]
, [ ("P",True)
, ("Q",False)
]
, [ ("P",True)
, ("Q",True)
]
]
But, mine were:
[[("P",True),("Q",True)],[("P",False),("Q",False)]]
So what is the proper implementation of the 'envs' function, the one that returns the expected result?
回答1:
What you want to do is get all combinations of True
and False
for the number of names, which can be done easily with replicateM
specialised to lists:
replicateM (length names) [False, True]
E.g. if length names == 2
, then this produces:
[ [False, False]
, [False, True]
, [True, False]
, [True, True]
]
What remains is just to zip each of these with the names themselves:
envs names =
[ zip names values
| let n = length names
, values <- replicateM n [False, True]
]
For envs ["P", "Q"]
this produces:
[ [("P", False), ("Q", False)]
, [("P", False), ("Q", True)]
, [("P", True), ("Q", False)]
, [("P", True), ("Q", True)]
]
And it works for any number of inputs, even 0, for which your original implementation would fail since you don’t match []
. It always returns 2n assignments:
-- 2^0 == 1
envs [] == [[]]
-- 2^3 == 8
envs ["P", "Q", "R"] ==
[ [("P", False), ("Q", False), ("R", False)]
, [("P", False), ("Q", False), ("R", True)]
, [("P", False), ("Q", True), ("R", False)]
, [("P", False), ("Q", True), ("R", True)]
, [("P", True), ("Q", False), ("R", False)]
, [("P", True), ("Q", False), ("R", True)]
, [("P", True), ("Q", True), ("R", False)]
, [("P", True), ("Q", True), ("R", True)]
]
来源:https://stackoverflow.com/questions/54047733/haskell-function-name-name-bool