首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >人工计算困惑(自然语言处理)

人工计算困惑(自然语言处理)
EN

Stack Overflow用户
提问于 2022-11-11 14:55:30
回答 1查看 89关注 0票数 0

下面是我写的代码,现在我想用Monad重写它。用do符号。我尝试了下面的do表示法,但是得到了输出。它似乎与我使用绑定的元组有关,它在原始代码中工作:

代码语言:javascript
复制
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造成的。这是正确的吗?我的概念误解在哪里?如何修复代码?

而且,我试图用状态单来重写它是正确的吗?

编辑:尝试回答下面的锻炼建议

我已经尝试了下面的内容,但是得到了一个解析器错误。

代码语言:javascript
复制
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-语句的两个分支更改为具有相同函数和参数的调用以进行测试。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-11 15:18:04

我认为你真正想要的是“用monad重写它”实际上是在州立单曲中重写它。如果您没有实际的monad类型,那么使用monad语法是没有好处的。

(普通的元组也可以作为一个单元组,但最好忽略它,它更令人困惑,而不是有用。)

在单一状态下表示特定随机计算的要点是,它避免了显式新版本的随机生成器的笨拙和易出错的情况。也就是说,你想要替换

代码语言:javascript
复制
  let (val, g') = R.random g
      (val', g'') = R.random g'

用简单的

代码语言:javascript
复制
  val <- random'
  val' <- random'

为了到达那里,我们先重新订购签名:

代码语言:javascript
复制
random_response :: a -> [a] -> (R.StdGen -> (a, R.StdGen))

括号中的部分基本上是State R.StdGen a。事实上,您可以很容易地重写它以获得签名。

代码语言:javascript
复制
random_response :: a -> [a] -> State R.StdGen a

我将把它作为一个练习,但将讨论giveRandomElement,这是目前的错误。请注意,generator只是一个全局常量,也就是说,giveRandomElement总是会产生列表中的相同元素。这不太好。

相反,这也应该有一个适当的随机类型,更好地再一次国家单一。你可以这样写:

代码语言:javascript
复制
giveRandomElement :: [a] -> State R.StdGen a
giveRandomElement lst = do
  let n = length lst
  rand <- state $ randomR (0, n-1)
  return $ lst !! rand
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74404325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档