将Haskell中的全局列表放到以生成唯一的随机值
我目前正在构建玩具餐计划申请,并决定在Haskell中写下后端,只是为了挑战自己。我认为我所遇到的问题在我认为我需要一些全局,可变的列表中可以记录以前的请求(它们不是同时提出的)。这是尤其是有问题的路线,特别是Random_value是绑定的:
getMeal :: Pipe -> ScottyM ()
getMeal pipe = post "/get_meal/:mid?" $ do
mid <- rescue (param "mid" :: ActionM Int) (\_ -> return 0)
doc <- access pipe master "risto" $ do
meal_count <- count $ select [] "meals"
random_value <- getStdRandom (randomR (0, meal_count - 1))
if mid == 0
then findOne $ select ["id" =: random_value] "meals"
else findOne $ select ["id" =: mid] "meals"
case doc of
Nothing -> text "Meal not found"
Just a -> json $ Meal (at "id" a) (at "name" a) (at "calories" a) (at "yield" a) (at "ingredients" a)
但是,您可以想象,如果此功能称为5个单独的时间,则可能会为餐点生成相同的值。在命令式的语言中,我将初始化一个限制5个项目的队列,然后使用它。探索使我相信国家单子很可能是我应该寻找的地方,经过一些实验,我想到了:
type GetState = [Int]
pushLast :: Int -> State GetState ()
pushLast v = state $ \(x:xs) -> ((), if length xs == 5 then v:init xs else v:xs)
checkLastFive :: Int -> State GetState Bool
checkLastFive v = state $ \xs -> (elem v xs, xs)
我认为这可能太复杂了,所以我也想到了:
pushLastGet :: Int -> State [Int] ()
pushLastGet n = do
s <- Control.Monad.State.get
if elem n s
then return ()
else Control.Monad.State.put (n:s)
主要问题:我正在努力解决这个问题。我想象的是(在Haskell/python like pseudocode中):
while True:
random_value <- getStdRandom (randomR (0, meal_count - 1))
if pushLastGet random_value != (): -- value was not in list
break
此外,我正在努力完全掌握应该初始化的初始状态,以及我的究竟是什么逻辑看起来像在Haskell中,并且在包裹它的单子的约束之内。
我还认为可能有一种聪明的非统一方法可以使用直到
,但是我的知识水平还没有。
I'm currently building a toy meal planning application and have decided to write the back-end in Haskell simply to challenge myself. The problem that I'm having is described in the title in which I believe I need some global, mutable list in which to record previous requests (they are not made at the same time). This is the route that is particularly in question, specifically where random_value is bound:
getMeal :: Pipe -> ScottyM ()
getMeal pipe = post "/get_meal/:mid?" $ do
mid <- rescue (param "mid" :: ActionM Int) (\_ -> return 0)
doc <- access pipe master "risto" $ do
meal_count <- count $ select [] "meals"
random_value <- getStdRandom (randomR (0, meal_count - 1))
if mid == 0
then findOne $ select ["id" =: random_value] "meals"
else findOne $ select ["id" =: mid] "meals"
case doc of
Nothing -> text "Meal not found"
Just a -> json $ Meal (at "id" a) (at "name" a) (at "calories" a) (at "yield" a) (at "ingredients" a)
However, as you can imagine, if this function is called 5 separate times, it may generate the same value for the meal. In an imperative language, I would initialize a queue with a limit of 5 items and be done with it. Exploration has led me to believe that the State monad is likely where I should be looking, and after some experimentation, I came up with:
type GetState = [Int]
pushLast :: Int -> State GetState ()
pushLast v = state $ \(x:xs) -> ((), if length xs == 5 then v:init xs else v:xs)
checkLastFive :: Int -> State GetState Bool
checkLastFive v = state $ \xs -> (elem v xs, xs)
I thought that this might be over-complicating it, so I also came up with:
pushLastGet :: Int -> State [Int] ()
pushLastGet n = do
s <- Control.Monad.State.get
if elem n s
then return ()
else Control.Monad.State.put (n:s)
The major problem that I'm having is a struggling with trying to solve this imperatively. I'm imagining something along the lines of (in Haskell/Python-like pseudocode):
while True:
random_value <- getStdRandom (randomR (0, meal_count - 1))
if pushLastGet random_value != (): -- value was not in list
break
Furthermore, I'm struggling to fully grasp exactly where and how an initial state should be initialized, and what exactly my logic looks like in Haskell and further within the constraints of the monads that wrap it.
I've also had the thought that there might be a clever non-monadic way of doing this perhaps using until
, but my knowledge level is not quite there yet.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论