Jiv*_*van 2 random haskell list
我正在尝试获得以下输出:
[(1,5,54), (1,6,34), (1,7,16), (2,5,59), (2,6,29), (2,7,71), (3,5,44), (3,6,67), (3,7,24)]
Run Code Online (Sandbox Code Playgroud)
这是笛卡尔积,[1..3], [5..7]其中每个结果元组都获得一个随机数作为其第三个元素。
我试过下面的代码
[(1,5,54), (1,6,34), (1,7,16), (2,5,59), (2,6,29), (2,7,71), (3,5,44), (3,6,67), (3,7,24)]
Run Code Online (Sandbox Code Playgroud)
问题是这会生成一个随机数并一直重复(假设这次是 42):
[(1,5,42), (1,6,42), (1,7,42), (2,5,42), (2,6,42), (2,7,42), (3,5,42), (3,6,42), (3,7,42)]
Run Code Online (Sandbox Code Playgroud)
然后我想,当然,让我们实际生成length [1..3] * length [5..7]数字:
hello :: IO [(Int, Int, Int)]
hello = do
g <- getStdGen
let zyx = do
x <- [1..3]
y <- [5..7]
z <- take 1 $ randomRs (1, 100) g
pure (x, y, z)
pure zyx
Run Code Online (Sandbox Code Playgroud)
但现在这将随机数列表组合到产品中:
[(1,5,66),(1,5,41) ... (1,6,66),(1,6,41) ... (1,7,66),(1,7,41)]
Run Code Online (Sandbox Code Playgroud)
是否有可能以直接方式获得所需的输出,从而避免最初构建二元组列表,然后使用生成的相同长度的随机数列表对其进行排序randomRs?
问题是笛卡尔积与 zip 操作完全不同。笛卡尔积的长度是其操作数长度的乘积,而 zip 结果的长度是其操作数长度的最小值。
我们仍然可以分两步操作:
$ ghci
?>
?> import System.Random
?> import Control.Applicative
?>
?> liftA2 (,) [1..3] [5..7]
[(1,5),(1,6),(1,7),(2,5),(2,6),(2,7),(3,5),(3,6),(3,7)]
?>
?> g0 = mkStdGen 4243
?> rds = randomRs (1,100) g0
?>
?> zip (liftA2 (,) [1..3] [5..7]) rds
[((1,5),24),((1,6),90),((1,7),79),((2,5),39),((2,6),96),((2,7),27),((3,5),96),((3,6),53),((3,7),77)]
?>
Run Code Online (Sandbox Code Playgroud)
所以我们差不多完成了。
?>
?> map (\((a,b),c) -> (a,b,c)) $ zip (liftA2 (,) [1..3] [5..7]) rds
[(1,5,24),(1,6,90),(1,7,79),(2,5,39),(2,6,96),(2,7,27),(3,5,96),(3,6,53),(3,7,77)]
?>
Run Code Online (Sandbox Code Playgroud)
或者:
?>
?> zipWith (\(a,b) c -> (a,b,c)) (liftA2 (,) [1..3] [5..7]) rds
[(1,5,24),(1,6,90),(1,7,79),(2,5,39),(2,6,96),(2,7,27),(3,5,96),(3,6,53),(3,7,77)]
?>
Run Code Online (Sandbox Code Playgroud)