A UUID looks something like e1631449-6321-4a58-920c-5440029b092e, and can
be used as an identifier for anything. Each 128-bit number, usually represented
as 32 hexadecimal digits, is generally assumed to be Universally Unique (hence
the name).
UUIDs have version numbers (1-5), which describe how they were created, and variant numbers (1-2) which describes how they are stored. This module can read all UUIDs, but can only currently create versions 3 (a namespaced, heirarchical system) and 4 (a randomly-generated UUID). It creates variant 1 UUIDs (probably the best choice if you don't have a specific need for variant 2), but can convert them to variant 2.
One type of UUID not defined above is the nil UUID. This is a "special form of UUID" defined as "00000000-0000-0000-0000-000000000000". I suppose it can be used as a placeholder for something that doesn't have a UUID yet?
Randomly-generated UUIDs are called version 4 UUIDs. This package provides a
Random.Generator for the elm/random library.
Generating a random UUID is, I think, the most straightforward way of making a UUID, and I see them used all the time. There are a couple of ways of using a generator to create a value, which are described nicely in the elm/random docs. Here is an example of how you might use the UUID generator:
type Comment = Comment String UUID
makeComment : String -> Random.Seed -> ( Comment, Random.Seed )
makeComment comment seed =
UUID.generator
|> Random.map (Comment comment)
|> Random.step seedUUIDs can be created using a namespace UUID and a name, which is then hashed to create a new UUID. The hash function used depends on the version of UUID: verison 3 UUIDs use MD5, and version 5 UUIDs use SHA-1. Currently, this package can only create version 3 UUIDs.
Once generated, these UUIDs can then be used as a namespace, making a hierarchy! I think this is pretty cool! You can use this method for making predictable UUIDs from data, and it also has the added bonus that you don't have to deal with random generators/seeds.
Start with an existing UUID as a "parent" UUID, and provide a name to create a new UUID.
grandparent = nil
parent = grandparent |> v3ChildNamed "parent"
parentsSibling = grandparent |> v3ChildNamed "parent's sibling"
child1 = parent |> v3ChildNamed "child1"
child2 = parent |> v3ChildNamed "child2"
cousin = parentsSibling |> v3ChildNamed "cousin"
UUID.canonical child2 == "4cacaf93-fcc5-3a02-bc41-c0a3e359e11d"The RFC defining UUIDs defines some base UUIDs to start your hierarchy.
A UUID for the DNS namespace, "6ba7b810-9dad-11d1-80b4-00c04fd430c8".
UUID.dns |> v3ChildNamed "elm-lang.org"A UUID for the URL namespace, "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
UUID.url |> v3ChildNamed "https://package.elm-lang.org"A UUID for the ISO object ID (OID) namespace, "6ba7b812-9dad-11d1-80b4-00c04fd430c8". I am not going to try to explain what an OID is, if you need to use this, you probably have a better grasp of them than I do!
UUID.oid |> v3ChildNamed "1.2.250.1"
A UUID for the X.500 Distinguished Name (DN) namespace, "6ba7b814-9dad-11d1-80b4-00c04fd430c8". I am not going to try to explain what a X.500 DN is, if you need to use this, you probably have a better grasp of them than I do!
You may have noticed that generator and v3ChildNamed make variant 1
UUIDs. If you need to create a variant 2 UUID, any UUID can be converted to a
variant 2 UUID with toVariant2. Note that variant 2 UUIDs cannot be converted
to variant 1 UUIDs.
Variant 2 UUIDs are very similar to variant 1 UUIDs, the main end-user difference being that they provide 1 fewer bit of randomness, but are a Microsoft standard. Note the single digit change in the following example:
-- c72c207b-0847-386d-bdbc-2e5def81cf81
var1UUID =
nil |> v3ChildNamed "hello world"
-- c72c207b-0847-386d-ddbc-2e5def81cf81
var2UUID =
var1UUID |> toVariant2You can attempt to create a UUID from a string. This function can interpret a fairly broad range of formatted (and mis-formatted) UUIDs, including ones with too much whitespace, too many (or not enough) hyphens, or uppercase characters.
fromString "c72c207b-0847-386d-bdbc-2e5def81cf811" == Err "UUID was not correct length"
fromString "c72c207b-0847-386d-bdbc-2e5def81cg81" == Err "UUID contained non-hexadecimal digits"
fromString "00000000-0000-0000-0000-000000000000" == Ok nil
fromString "urn:uuid:00000000-0000-0000-0000-000000000000" == Ok nil
fromString "{00000000-0000-0000-0000-000000000000}" == Ok nil
fromString "\n\n {urn:uuid: 00 000000-0000-0000-0-000-000000000000}" == Ok nilNote: if you are decoding from JSON, you may like json-extra's fromResult function.
uuidDecoder = Json.Decode.string |> Json.Decode.andThen (Json.Decode.Extra.fromResult << UUID.fromString)
UUIDs are generally represented by 32 hexadecimal digits in the form
00112233-4455-M677-N899-aabbccddeeff, where the four bits at position M
denote the UUID version, and the first two or three bits at position N denote
the variant. This is the "canonical" representation, but there is also a
Microsoft GUID representation and a URN representation.
This is just an alias for canonical, the most common way to represent a UUID.
canonical someUUID == toString someUUIDConvert UUID to canonical textual representation
canonical nil == "00000000-0000-0000-0000-000000000000"Convert UUID to Microsoft GUID representation
microsoftGUID nil == "{00000000-0000-0000-0000-000000000000}"Convert UUID to URN-namespaced representation
urn nil == "urn:uuid:00000000-0000-0000-0000-000000000000"Sometimes you may need to check a UUID's version, variant, or whether it's nil.
If the bits of the UUID indicate that it is properly versioned UUID e.g. version 1,
returns e.g. Just 1. Otherwise, Nothing!
version nil == Nothing
version (nil |> v3ChildNamed "Hello") == Just 3True if the given UUID is the given version number. Always False is the
integer provided is not 1, 2, 3, 4 or 5!
isVersion 8 someUUID -- always False!
isVersion 4 nil -- False!
someJsonValue
|> Json.Decode.decodeValue UUID.decoder
|> UUID.isVersion 5
isVersion 3 (nil |> v3ChildNamed "hello") -- TrueIf the bits of the UUID indicate that it is a variant 1 or 2 UUID, returns
Just 1 or Just 2, respectively. Otherwise, Nothing!
variant nil == Nothing
variant (nil |> v3ChildNamed "Hello") == Just 1True if the given UUID is the given variant number. Always False is the
integer provided is not 1 or 2!
isVariant 4 someUUID -- Always False, variant 4 doesn't exist!
someJsonValue
|> Json.Decode.decodeValue UUID.decoder
|> UUID.isVariant 1
isVariant 2 (someUUID |> toVariant2) -- TrueSometimes you may need to ensure that a UUID is definitely a certain version or variant. If you're decoding from JSON, you may find the following functions useful in conjunction with json-extra's fromResult function.
uuidDecoder = Json.Decode.string |> Json.Decode.andThen (Json.Decode.Extra.fromResult << UUID.fromString) |> Json.Decode.andThen (Json.Decode.Extra.fromResult << UUID.checkVersion 4) |> Json.Decode.andThen (Json.Decode.Extra.fromResult << UUID.checkVariant 1)
Check which version a UUID is, and if it's not the right one, return an Err.
(nil |> v3ChildNamed "hello" |> checkVersion 4) == Err "UUID is not Version 4"
(nil |> checkVersion 1) == Err "UUID does not define a valid version"
(someVersion4UUID |> checkVersion 4) == Ok someVersion4UUIDCheck which variant a UUID is, and if it's not the right one, return an Err.
(nil |> v3ChildNamed "hello" |> checkVariant 2) == Err "UUID is not variant 2"
(nil |> checkVariant 2) == Err "UUID does not define a valid variant"
(someVariant1UUID |> checkVariant 1) == Ok someVariant1UUIDA simple function to use while chaining Results. Makes sure the UUID
you're dealing with isn't the Nil UUID!
uuid =
someString
|> UUID.fromString
|> Result.andThen (UUID.checkNotNil 4)
This modules provides a UUID type, and functions to work with them. It is an opaque type, which basically means you have to use the provided functions if you want to do anything with it!
Here is an example of a
Bookmodel, which uses UUIDs to identify both the book and its authors: