下面是我写的代码,现在我想用Monad重写它。用do符号。我尝试了下面的do表示法,但是得到了输出。它似乎与我使用绑定的元组有关,它在原始代码中工作:
seed::Int
seed = 2
giveList :: [Int]
giveList = [8,9,4,5,2]
generator = mkStdGen seed
giveRandomElement :: [a] -> a
giveRandomElement lst = lst !! rand where
n = length lst
(rand, _) = randomR (0,(n-1)) generator
random_response :: R.StdGen -> a -> [a] -> (a, R.StdGen)
random_response g true_answer answers =
let (val, g') = R.random g
(val', g'') = R.random g' :: (Bool, R.StdGen)
in if val then (true_answer, g'')
else (giveRandomElement answers , g'')
random_response_monad :: R.StdGen -> a -> [a] -> (a, R.StdGen)
random_response_monad g true_answer answers = do
(val, g') <- R.random g :: (Bool, R.StdGen)
(val', g'') <- R.random g' :: (Bool, R.StdGen)
if val then return (true_answer, g'')
else return (giveRandomElement answers, g'')
OUTPUT:
error:
* Couldn't match expected type `StdGen'
with actual type `(Bool, StdGen)'
* In the pattern: (val, g')
In a stmt of a 'do' block: (val, g') <- random g :: (Bool, StdGen)
In the expression:
do (val, g') <- random g :: (Bool, StdGen)
(val', g'') <- random g' :: (Bool, StdGen)
if val then
return (true_answer, g'')
else
return (giveRandomElement answers, g'')
(val, g') <- R.random g :: (Bool, R.StdGen)我怀疑我得到的类型错误是由于<-而不是let-binding造成的。这是正确的吗?我的概念误解在哪里?如何修复代码?
而且,我试图用状态单来重写它是正确的吗?
编辑:尝试回答下面的锻炼建议
我已经尝试了下面的内容,但是得到了一个解析器错误。
random_response_monad :: a -> [a] -> State R.StdGen a
random_response_monad true_answer answers = do
let random' = state $ randomR(0,1)
val <- random'
val' <- random'
if val then giveRandomElement answers
else giveRandomElement answers请注意,我将if-语句的两个分支更改为具有相同函数和参数的调用以进行测试。
发布于 2022-11-11 15:18:04
我认为你真正想要的是“用monad重写它”实际上是在州立单曲中重写它。如果您没有实际的monad类型,那么使用monad语法是没有好处的。
(普通的元组也可以作为一个单元组,但最好忽略它,它更令人困惑,而不是有用。)
在单一状态下表示特定随机计算的要点是,它避免了显式新版本的随机生成器的笨拙和易出错的情况。也就是说,你想要替换
let (val, g') = R.random g
(val', g'') = R.random g'用简单的
val <- random'
val' <- random'为了到达那里,我们先重新订购签名:
random_response :: a -> [a] -> (R.StdGen -> (a, R.StdGen))括号中的部分基本上是State R.StdGen a。事实上,您可以很容易地重写它以获得签名。
random_response :: a -> [a] -> State R.StdGen a我将把它作为一个练习,但将讨论giveRandomElement,这是目前的错误。请注意,generator只是一个全局常量,也就是说,giveRandomElement总是会产生列表中的相同元素。这不太好。
相反,这也应该有一个适当的随机类型,更好地再一次国家单一。你可以这样写:
giveRandomElement :: [a] -> State R.StdGen a
giveRandomElement lst = do
let n = length lst
rand <- state $ randomR (0, n-1)
return $ lst !! randhttps://stackoverflow.com/questions/74404325
复制相似问题