Happstack为每个请求获得新的StdGen?

时间:2013-06-15 18:07:52

标签: haskell random monad-transformers happstack

我有一个简单的小Happstack应用程序,它显示一个带有电子邮件字段和随机问题字段的表单,以帮助打击垃圾邮件。要获取一个随机数,我在getStdGen函数中使用main并将其传递给我创建html的函数。问题是使用相同的StdGen因此我的随机值不是随机的,除非我重新启动应用程序。

这是Main.hs的样子:

{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}                                                                                                

module Main where                                                                                                                                      

import Happstack.Lite                                                                                                                                  
import qualified Pages.Contact as Contact                                                                                                                                                                                                                                
import System.Random                                                                                                                                   

main :: IO ()                                                                                                                                          
main = do                                                                                                                                              
    gen <- getStdGen                                                                                                                                   
    serve Nothing $ pages gen                                                                                                                          

pages :: StdGen -> ServerPart Response                                                                                                                 
pages g = msum                                                                                                                                         
    [ dir "contact" $ Contact.page g                                                                                                                   
    ... Other irrelevant pages                                                                                                           
    ]

这是使用StdGen来检索随机问题ID的函数:

getRandomQID :: StdGen -> Int                                                                                                             
getRandomQID g =                                                                                                                                       
    let (rpercent, _) = random g :: (Float, StdGen)                                                                                                    
        rid           = rpercent * questionsAmount                                                                                                    
    in  round rid                                                                                                                

questionsAmount :: (Num a) => a                                                                                                                        
questionsAmount = (fromIntegral . length) questions

解决此问题最优雅的方法是什么?

1 个答案:

答案 0 :(得分:1)

在我写这个问题时,我找到了一个适用于Happstack crash course (templates)的解决方案。

在返回类型为ServerPart Response的路由中,您可以使用liftIO monad转换器来执行IO操作。有一个名为randomRIO的方便函数,它从一个元组的输入生成一个随机Int,其中两个Int作为范围,如下所示:

page :: ServerPart Response
page = do 
    randID <- liftIO $ randomRIO (0, max)
    ... Code to generate response ...
    where max = length questions

randomRIO可以在System.Random中找到,liftIO可以在Control.Monad.Trans中找到。