Loops 哈斯克尔:洗牌牌组
我在一个实验室里工作,在那里我们处理随机性和单子 实验室的组成部分包括:Loops 哈斯克尔:洗牌牌组,loops,haskell,random,shuffle,Loops,Haskell,Random,Shuffle,我在一个实验室里工作,在那里我们处理随机性和单子 实验室的组成部分包括: 编写一个函数randR,生成给定范围内的随机数 编写一个函数rolltowdice,模拟滚动两个骰子 编写一个函数removeCard,该函数从播放卡列表中随机删除一张卡 编写一个函数shuffleDeck,它将取出的牌放在牌组前面,然后重复它自己,直到牌组完全洗牌 我已经完成了1、2和3,但我在4方面遇到了问题 以下是给定的代码: RandState.hs module RandState where import UC
module RandState where
import UCState
import System.Random
-- In order to generate pseudo-random numbers, need to pass around generator
-- state in State monad
type RandState a = State StdGen a
-- runRandom runs a RandState monad, given an initial random number generator
runRandom :: RandState a -> StdGen -> a
runRandom (State f) s = res
where (res, state) = f s
-- rand is a helper function that generates a random instance of any
-- type in the Random class, using the RandState monad.
rand :: Random a => RandState a
rand = do
gen <- get
let (x, gen') = random gen
put gen'
return x
这是我的代码,我只是在RandState.hs中编写的,因为我不知道如何导入它(帮助导入也很好,尽管这不是我最关心的):
我想问题在于迭代获取一个值,将函数应用于该值,将函数应用于结果,依此类推,返回一个无限的结果列表。我正在处理一个iterate函数,它接受一个列表并返回一张卡片,因此结果不能传递给下一个迭代。解决这个问题的更好方法是什么(4)?我还担心我的removeCard函数有点笨拙,因为它只是将“已删除”的卡放在前面,我这样做是为了使shuffleDeck更容易编写。如有必要,解决此问题的更好方法是什么(3)
谢谢,
Jeff您应该停止在函数中运行random。您应该只在实际需要结果时使用
runRandom
(例如,打印结果,因为您不能在monad中执行此操作)。试图从monad中“逃脱”是一项徒劳的任务,您只会产生令人困惑且常常无法运行的代码。所有函数的最终输出都将在monad中,因此无论如何都不需要转义
注意
gen <- get
let n = runRandom (randR(1, length (deck))) gen :: Int
对:
try = do
a <- randomIO :: IO Int
let b = runRandom (randR (0,10)) (mkStdGen a) :: Int -- 'execute' the randstate monad
return $ a + b
try=do
a我最好的客人是从f中取出“head$”,因为您希望迭代整个牌组(而不是第一张牌!)。它至少应该进行打字检查。编辑:是的,就是这样,你必须修正take参数,但你应该能够解决它。import
应该导入东西:)感谢MdxBhmt,我从f中删除了head$,然后将head映射到迭代列表。不过,我无法让shuffleDeck显示其结果,显然是因为没有(Show(RandState[PlayingCard])的实例。有什么想法吗?还有jozefg,我昨晚已经试过导入了,但没有成功,但我现在又试了一次,成功了。也许你的评论是x因素,所以谢谢。@user2967411你不能打印RandState,因为它是一个函数,你必须runRandom
并打印结果谢谢!这很有道理。现在我有一个关于掷骰子的问题。我回去后发现,这个问题要求我在实现中使用randR。所以我希望我能写一个更新的答案,并附上回复。
RandState.hs:88:31:
Occurs check: cannot construct the infinite type: a0 = [a0]
Expected type: [a0] -> [a0]
Actual type: [a0] -> a0
In the first argument of `iterate', namely `f'
In the second argument of `take', namely `(iterate f deck)'
In the second argument of `($)', namely `take 52 (iterate f deck)'
gen <- get
let n = runRandom (randR(1, length (deck))) gen :: Int
n <- randR (1, length deck)
shuffleR [] = return []
shuffleR xs = do
(y:ys) <- removeR xs -- 1
zs <- shuffleR ys -- 2
return (y:zs) -- 3
randSum :: (Num b, Random b) => State StdGen b
randSum = do
a <- randR (1,6)
b <- randR (1,6)
return $ a + b
try = do
a <- randomIO :: IO Int
b <- randR (0,10) :: RandState Int
return $ a + b -- monads don't match!
try = do
a <- randomIO :: IO Int
let b = runRandom (randR (0,10)) (mkStdGen a) :: Int -- 'execute' the randstate monad
return $ a + b