使用 Elm 生成随机 UUIDv4

Sér*_*hin 2 random uuid elm

我正在尝试在循环中生成随机 UUID v4:

    randomUuid =
         -- TODO: find a way to generate random uuid for variableId

    updatedVariables =              
         group.variables |> List.map (\variable -> { variable | id = randomUuid })
Run Code Online (Sandbox Code Playgroud)

我阅读了elm/random和elm/uuid的文档,但找不到如何在不使用种子的情况下生成 UUID。

我唯一能做的就是:

newUuid : Random.Seed -> ( String, Random.Seed )
newUuid seed =
    seed
        |> Random.step UUID.generator
        |> Tuple.mapFirst UUID.toString
Run Code Online (Sandbox Code Playgroud)

我将 elm/random 视为一个independentSeed函数,但我无法让它生成种子。

我想要实现的节点相当于randomUuid:

    randomUuid =
         -- TODO: find a way to generate random uuid for variableId

    updatedVariables =              
         group.variables |> List.map (\variable -> { variable | id = randomUuid })
Run Code Online (Sandbox Code Playgroud)

我觉得我可能在这里遗漏了 Elm 中的一些重要概念,但我自己无法弄清楚。任何帮助或指示将不胜感激。

Jak*_*mpl 6

生成随机值是一种效果,因此纯语言不能仅仅执行它。

然而,有一个纯粹的随机性版本,它使用随机种子。它们具有这样的属性:每次使用相同的种子生成一个值时,您都会得到相同的值 - 因此这只是一个纯粹的计算,并且在纯粹的上下文中是完全可以的。

Elm 允许您将效果执行为,即从和函数Cmd返回的内容。因此,您可以选择的一种选择是始终在需要之前返回,然后在处理消息时执行计算。initupdateRandom.generate GotANewUUID UUID.generator GotANewUUID

另一种选择是跟踪随机种子。您可以从确定性的开始Random.initialSeed(可能不是您想要的 UUID,因为它们在程序的每次运行中都完全相同),或者在您init返回的函数中Random.generate GotNewSeed Random.independentSeed。然后将种子存储在模型中。每次需要生成新的 UUID 时,请使用newUuid上面的函数,确保存储新的种子。

这是一个例子:

import Random
import UUID

type alias Thing = 
    { id : String
    -- , some other stuff
    }

type alias Model =
    { seed : Random.Seed
    , stuff : List Thing
    }

type Msg
    = GotNewSeed Random.Seed 
    | AddAThing Thing
    | AddABunchOfThings (List Thing)

init : () -> (Model, Cmd Msg)
init flags =
    ({ seed = Random.initialSeed 567876567 
    -- Let's start with a deterministic seed
    -- so you don't need to deal with Maybe Seed later
     , stuff = []
    }, Random.generate GotNewSeed Random.independentSeed
    )

update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    case msg of
        GotNewSeed seed ->
            ({model | seed = seed}, Cmd.none)
    
        AddAThing thing ->
            let
                (newId, newSeed) = 
                     newUuid model.seed
            in
            ({ model | stuff = { thing | id = newId } :: model.stuff
             , seed = newSeed }
            , Cmd.none
            )

         AddABunchOfThings things ->
             let
                 (newStuff, newSeed) =
                      List.foldl (\thing (stuff, seed) ->
                          newUuid seed
                              |> Tuple.mapFirst (\id -> 
                                  { thing | id = id } :: stuff
                              )
                      ) (model.stuff, model.seed) things
              in
              ({model | stuff = newStuff, seed = newSeed}, Cmd.none)

          
 

Run Code Online (Sandbox Code Playgroud)