程序返回'0'和'1'长度为N的所有可能组合。
addToElement :: String -> String -> String
addToElement element symbol = element ++ symbol
addOneToElement :: String -> String
addOneToElement element = addToElement element "1"
addZeroToElement :: String -> String
addZeroToElement element = addToElement element "0"
processListOnce :: [String] -> [String]
processListOnce lst = do
let s1 = map addOneToElement lst
let s2 = map addZeroToElement lst
s1 ++ s2
processList :: [String] -> Integer -> [String]
processList lst 1 = processListOnce lst
processList lst n = do
let tmp = processListOnce(lst)
processList tmp (n - 1)
{-
processList2 :: [String] -> Integer -> [String]
processList2 lst n = iterate (map processListOnce) lst !! n
-}
main = do
let s = processList ["0", "1"] 2
let ss = show s
putStrLn ss
这是我的第一个Haskell计划,所以如果你帮助我,我将感激不尽:
首先请重构我的代码Haskell-way。我已经知道一个神奇的refactring:
Control.Monad.replicateM n [0,1]
但这种解决方案不适合学习目的:)
为什么我不能使用ProcessList2代替ProcessList并获取错误:
all_possible_combinations.hs:44:51:
Couldn't match expected type `[Char]' against inferred type `Char'
Expected type: [String]]
Inferred type: [String]
In the second argument of `iterate', namely `lst'
In the first argument of `(!!)', namely
`iterate (map processListOnce) lst'
有没有办法跳过(不使用)processList中的'tmp'变量?我试过了,但得到了错误:
processList :: [String] -> Integer -> [String]
processList lst 1 = processListOnce lst
processList lst n = processList processListOnce(lst) (n - 1)
all_possible_combinations.hs:39:32:
Couldn't match expected type `[String]'
against inferred type `[String] -> [String]'
In the first argument of `processList', namely `processListOnce'
In the expression: processList processListOnce (lst) (n — 1)
In the definition of `processList':
processList lst n = processList processListOnce (lst) (n — 1)
提前致谢。
答案 0 :(得分:9)
首先请重构我的代码Haskell-way。我已经知道一个神奇的refactring:
Control.Monad.replicateM n [0,1]
但这种解决方案不适合学习目的:)
实际上,虽然我当然不希望有新的Haskell想出这样的解决方案,但我认为理解这个版本对非常有利于学习目的。
常规replicate
函数非常简单:它会重复创建一个重复相同元素的列表。这也是replicateM
所做的第一步:
> replicate 2 ["0", "1"]
[["0", "1"], ["0", "1"]]
replicateM
所做的第二步是根据元素的Monad
对序列进行“排序”,将一个monadic值列表[m a]
转换为monadic值列表m [a]
。这样做是在某种意义上“结合”每个monadic值的结构,其中“combine”的具体含义取决于特定的monad。
作为Monad
,列表代表尝试多种可能性之类的内容。因此,当我们“排序”这些值时,这意味着每一步都会分别尝试所有可能性,并收集所有可能的结果。
因此,["0", "1"]
是一个monadic值,表示尝试两种不同的可能性。 [["0", "1"], ["0", "1"]]
是重复两次的monadic值的列表。为了对该列表进行排序,我们从列表的第一个元素中获取每种可能性,将其用作结果列表的头部,然后继续直到结束。因为每组可能性是相同的,所以最终结果是每个可能项目的所有可能组合:
> replicateM 2 ["0", "1"]
[["0","0"],["0","1"],["1","0"],["1","1"]]
答案 1 :(得分:8)
关于制作Haskelly,这里的解决方案不是纯粹的魔法(因为复制M可能是)
onesAndZeroes 0 = [[]]
onesAndZeroes n = [x:xs | x <- [0,1], xs <- onesAndZeroes (n-1)]
由于您不熟悉haskell,如果您不了解它,可能有助于阅读list comprehensions。
答案 2 :(得分:5)
有没有办法在processList中跳过(不使用)'tmp'变量?我试过了,但得到了错误:
此定义使用了错误的优先级。你应该写
processList lst n = processList (processListOnce lst) (n - 1)
-- # ^ ^
为什么我不能使用ProcessList2代替ProcessList并获取错误:
processListOnce
已经是[String] -> [String]
功能。如果您使用map processListOnce
,它将成为[[String]] -> [[String]]
函数。因此,请删除map
。
processList2 lst n = iterate processListOnce lst !! n
答案 3 :(得分:0)
另一种解决方案:
onesAndZeroes n = combo n ["0", "1"]
where combo 1 cs = cs
combo n cs = combo (n-1) (f cs)
f = concatMap (\x -> ['0':x, '1':x])
和其他人一样,我认为replicateM将是我的第一选择,但如果我要避免这样做,那将是我的解决方案。也许不如列表理解解决方案清晰/简洁,但我发现尾调用递归非常优雅。