将Haskell中的全局列表放到以生成唯一的随机值

发布于 2025-02-02 07:01:09 字数 1778 浏览 2 评论 0原文

我目前正在构建玩具餐计划申请,并决定在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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文