Esc
Start typing to search...

ValueLabelSet Module

Bidirectional mappings between integer values and human-readable labels.

The ValueLabelSet module provides functions for creating and manipulating value label sets, which map integer codes to descriptive strings. This is particularly useful for working with survey data, coded variables, and STATA-style value labels.

Common patterns

import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
gender |> ValueLabelSet.label 1   -- Just "Male"

Type-safe value labels

Define integer-to-label mappings directly in enum types using ValueLabel, then extract them with fromType:

import ValueLabelSet

type Gender
    = Male (ValueLabel 1 "Male")
    | Female (ValueLabel 2 "Female")

let labels = ValueLabelSet.fromType Gender
labels |> ValueLabelSet.label 1   -- Just "Male"

fromType is a compiler intrinsic that reads the mappings at compile time. It requires all variants to have exactly one ValueLabel field, and integer values must be unique.

Enum variant labels

Labels can also be enum variants with display labels:

type AgeGroup = Young "<30" | Middle "30-60" | Old ">60"
ValueLabelSet.fromList [(1, AgeGroup::Young), (2, AgeGroup::Middle)]

Functions

Create

ValueLabelSet.fromList

[(Int, a)] -> ValueLabelSet

Create a ValueLabelSet from a list of (value, label) pairs. Labels can be strings or enum variants (using display label or variant name).

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.label 1 gender  -- Just "Male"
Try it

See also: ValueLabelSet.empty, ValueLabelSet.insert

ValueLabelSet.fromType

TypeName -> ValueLabelSet

Create a ValueLabelSet from a ValueLabel enum type at compile time.

The compiler reads the ValueLabel fields from the enum definition and builds the mapping statically. All variants must have exactly one ValueLabel field, and integer values must be unique.

Example:
import ValueLabelSet

enum Gender
    = Male (ValueLabel 1 "Male")
    | Female (ValueLabel 2 "Female")

let labels = ValueLabelSet.fromType Gender
labels |> ValueLabelSet.label 1   -- Just "Male"
Try it

Notes: This is a compiler intrinsic — the type is resolved at compile time, not at runtime. The type name is passed unquoted (not as a string).

See also: ValueLabelSet.fromList

ValueLabelSet.empty

ValueLabelSet

Create an empty ValueLabelSet.

Example:
import ValueLabelSet

let vls = ValueLabelSet.fromList []
    |> ValueLabelSet.insert 1 "Yes"
    |> ValueLabelSet.insert 0 "No"
ValueLabelSet.size vls  -- 2
Try it

See also: ValueLabelSet.fromList

ValueLabelSet.insert

Int -> String -> ValueLabelSet -> ValueLabelSet

Insert a single value-label pair into the set.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
    |> ValueLabelSet.insert 9 "Unknown"
ValueLabelSet.size gender  -- 3
Try it

See also: ValueLabelSet.fromList

Lookup

ValueLabelSet.label

Int -> ValueLabelSet -> Maybe String

Get the label for a value.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
let found = ValueLabelSet.label 1 gender    -- Just "Male"
let missing = ValueLabelSet.label 9 gender  -- Nothing
missing
Try it

See also: ValueLabelSet.value

ValueLabelSet.value

String -> ValueLabelSet -> Maybe Int

Get the value for a label (reverse lookup).

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
let found = ValueLabelSet.value "Female" gender   -- Just 2
let missing = ValueLabelSet.value "Other" gender  -- Nothing
missing
Try it

See also: ValueLabelSet.label

Query

ValueLabelSet.size

ValueLabelSet -> Int

Get the number of labels.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.size gender  -- 2
Try it

See also: ValueLabelSet.isEmpty

ValueLabelSet.isEmpty

ValueLabelSet -> Bool

Check if the label set is empty.

Example:
import ValueLabelSet

let a = ValueLabelSet.isEmpty (ValueLabelSet.fromList [])  -- True
let b = ValueLabelSet.isEmpty (ValueLabelSet.fromList [(1, "Yes")])  -- False
b
Try it

See also: ValueLabelSet.size

ValueLabelSet.hasValue

Int -> ValueLabelSet -> Bool

Check if a value has a label.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
let found = ValueLabelSet.hasValue 1 gender    -- True
let missing = ValueLabelSet.hasValue 9 gender  -- False
missing
Try it

See also: ValueLabelSet.hasLabel

ValueLabelSet.hasLabel

String -> ValueLabelSet -> Bool

Check if a label exists.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
let found = ValueLabelSet.hasLabel "Male" gender    -- True
let missing = ValueLabelSet.hasLabel "Other" gender  -- False
missing
Try it

See also: ValueLabelSet.hasValue

ValueLabelSet.coverage

[Int] -> ValueLabelSet -> { labeled: [Int], unlabeled: [Int], unused: [Int] }

Check coverage of values against the label set. Returns which values have labels, which don't, and which labels have no matching values.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female"), (9, "Unknown")]
let seen_values = [1, 2, 2, 1, 3]
let report = ValueLabelSet.coverage seen_values gender
-- report.labeled   = [1, 2]   (values with labels)
-- report.unlabeled = [3]      (values without labels)
-- report.unused    = [9]      (labels with no matching value in data)
Try it

ValueLabelSet.describe

ValueLabelSet -> String

Return a formatted table showing all value-label mappings.

Example:
import ValueLabelSet
import IO

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female"), (9, "Unknown")]
IO.println (ValueLabelSet.describe gender)
-- Value | Label
-- ------+----------
--     1 | Male
--     2 | Female
--     9 | Unknown
Try it

Convert

ValueLabelSet.toList

ValueLabelSet -> [(Int, String)]

Convert to a list of (value, label) pairs.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.toList gender  -- [(1, "Male"), (2, "Female")]
Try it

See also: ValueLabelSet.fromList

ValueLabelSet.values

ValueLabelSet -> [Int]

Get all values in the label set.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.values gender  -- [1, 2]
Try it

See also: ValueLabelSet.labels

ValueLabelSet.labels

ValueLabelSet -> [String]

Get all labels in the label set.

Example:
import ValueLabelSet

let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.labels gender  -- ["Male", "Female"]
Try it

See also: ValueLabelSet.values

Transform

ValueLabelSet.merge

ValueLabelSet -> ValueLabelSet -> ValueLabelSet

Merge two label sets (first takes priority on conflicts).

Example:
import ValueLabelSet

let a = ValueLabelSet.fromList [(1, "Yes"), (2, "No")]
let b = ValueLabelSet.fromList [(2, "Nope"), (3, "Maybe")]
let merged = ValueLabelSet.merge a b
-- 1 = "Yes", 2 = "No" (a wins conflict), 3 = "Maybe"
ValueLabelSet.size merged  -- 3
Try it

ValueLabelSet.filter

[Int] -> ValueLabelSet -> ValueLabelSet

Filter to only include values in the given list.

Example:
import ValueLabelSet

let status = ValueLabelSet.fromList [(1, "Active"), (2, "Inactive"), (3, "Pending")]
let active_only = ValueLabelSet.filter [1, 3] status
ValueLabelSet.size active_only  -- 2
Try it

ValueLabelSet.remap

[(Int, Int)] -> ValueLabelSet -> ValueLabelSet

Remap values according to a list of (old, new) pairs.

Example:
import ValueLabelSet

-- Recode 1/2 to 0/1
let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
let recoded = ValueLabelSet.remap [(1, 0), (2, 1)] gender
ValueLabelSet.label 0 recoded  -- Just "Male"
Try it

ValueLabelSet.invert

ValueLabelSet -> Maybe ValueLabelSet

Invert the label set (swap values and labels). Returns Nothing if labels aren't numeric.

Example:
import ValueLabelSet

-- Labels are numeric strings, so invert works
let vls = ValueLabelSet.fromList [(1, "2"), (2, "1")]
ValueLabelSet.invert vls  -- Just (ValueLabelSet with 1 -> "2", 2 -> "1" swapped)

-- Labels are not numeric, so invert returns Nothing
let gender = ValueLabelSet.fromList [(1, "Male"), (2, "Female")]
ValueLabelSet.invert gender  -- Nothing
Try it