fmt

This module provides functions for creating formatting specifications and generating strings from those specificaitons in a type-safe way.

Overview

For additional information, check out the examples provided in this module’s documentation, as well as those in the README and the tests, which can be found in the project repository.

Note: The examples in this file use functions from the gleeunit package for illustration.

Types

Fmt is an opaque type that represents a formatting specification.

pub opaque type Fmt(a, b)

Functions

pub fn a(show show: fn(a) -> String) -> Fmt(b, fn(a) -> b)

a(show) returns a format specification for a value of type a given a function show that converts values of type a to values of type String.

This is useful for formatting custom types or other compound data types.

Here is an example of formatting an integer list (List(Int)):

import fmt
import gleam/int
import gleam/list
import gleam/string
import gleeunit/should

pub fn formatting_int_list_test() {
  let show_list = fn(lst) {
    lst
    |> list.map(int.to_string)
    |> string.join(with: "; ")
  }

  fmt.lit("[")
  |> fmt.cat(fmt.a(show_list))
  |> fmt.cat(fmt.lit("]"))
  |> fmt.sprintf1([1, 2, 3])
  |> should.equal("[1; 2; 3]")
}

Here is an example of formatting a custom data type:

import fmt
import gleam/float
import gleam/int
import gleam/list
import gleam/string
import gleeunit/should

type Either(a, b) {
  First(a)
  Second(b)
}

fn either_to_string(
  either: Either(a, b),
  a_to_string: fn(a) -> String,
  b_to_string: fn(b) -> String,
) -> String {
  case either {
    First(a) -> "First: " <> a_to_string(a)
    Second(b) -> "Second: " <> b_to_string(b)
  }
}

pub fn formatting_custom_types_test() {
  fmt.lit("Which is it? ")
  |> fmt.cat(fmt.a(show: either_to_string(_, int.to_string, float.to_string)))
  |> fmt.sprintf1(Second(2.71828))
  |> should.equal("Which is it? Second: 2.71828")
}
pub fn bool() -> Fmt(a, fn(Bool) -> a)

bool() returns a format specification for a boolean value. You could think of this as a placeholder that must be filled with a value of the type Bool.

pub fn cat(
  fmt_left: Fmt(a, b),
  fmt_right: Fmt(c, a),
) -> Fmt(c, b)

cat(fmt_left, fmt_right) concatenates the two formatting specifications.
This is the way to combine little formatting specifications into one big formatting specification. You would normally compose these with the pipe (|>).

import fmt
import gleeunit/should

pub fn cat_test() {
  fmt.lit("Name: ")
  |> fmt.cat(fmt.string())
  |> fmt.cat(fmt.lit("; Age: "))
  |> fmt.cat(fmt.int())
  |> fmt.sprintf2("Juan", 45)
  |> should.equal("Name: Juan; Age: 45")
}
pub fn float() -> Fmt(a, fn(Float) -> a)

float() returns a format specification for a floating-point value. You could think of this as a placeholder that must be filled with a value of the type Float.

pub fn int() -> Fmt(a, fn(Int) -> a)

int() returns a format specification for an integer value. You could think of this as a placeholder that must be filled with a value of the type Int.

pub fn lit(str: String) -> Fmt(a, a)

lit(str) returns a format specification for the literal string value provided by the argument str.

import fmt
import gleeunit/should

pub fn lit_test() {
  fmt.lit("Hello, Gleam!")
  |> fmt.sprintf
  |> should.equal("Hello, Gleam!")
}
pub fn sprintf(fmt: Fmt(String, a)) -> a

sprintf(fmt) takes a formatting specification and returns a curried function for generating the specified string.

You likely use the sprintfN variants of this function rather than this one, as those eliminate the need to work with the curried functions.

Here is an example. I have annotated some of the types, which may clarify some things.

pub fn sprintf_test() {
  let fmt: fmt.Fmt(String, fn(String) -> fn(Int) -> fn(Bool) -> String) =
    fmt.lit("Name: ")
    |> fmt.cat(fmt.string())
    |> fmt.cat(fmt.lit("; Age: "))
    |> fmt.cat(fmt.int())
    |> fmt.cat(fmt.lit("; Acct. Active: "))
    |> fmt.cat(fmt.bool())

  let f: fn(String) -> fn(Int) -> fn(Bool) -> String = fmt.sprintf(fmt)

  f("Juan")(45)(True)
  |> should.equal("Name: Juan; Age: 45; Acct. Active: True")

Alternatively, you may rather use the uncurry function with the matching arity so that you can continue the pipeline.

pub fn sprintf_uncurry_test() {
  fmt.lit("Name: ")
  |> fmt.cat(fmt.string())
  |> fmt.cat(fmt.lit("; Age: "))
  |> fmt.cat(fmt.int())
  |> fmt.cat(fmt.lit("; Acct. Active: "))
  |> fmt.cat(fmt.bool())
  |> fmt.sprintf
  |> fmt.uncurry3("Juan", 45, True)
  |> should.equal("Name: Juan; Age: 45; Acct. Active: True")
}
pub fn sprintf1(fmt: Fmt(String, fn(a) -> b), x1: a) -> b

sprintf1(fmt, x1) takes a formatting specification fmt and a value x1, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf2(
  fmt: Fmt(String, fn(a) -> fn(b) -> c),
  x1: a,
  x2: b,
) -> c

sprintf2(fmt, x1, x2) takes a formatting specification fmt and two values x1 and x2, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf3(
  fmt: Fmt(String, fn(a) -> fn(b) -> fn(c) -> d),
  x1: a,
  x2: b,
  x3: c,
) -> d

sprintf3(fmt, x1, x2, x3) takes a formatting specification fmt and three values x1, x2, and x3, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf4(
  fmt: Fmt(String, fn(a) -> fn(b) -> fn(c) -> fn(d) -> e),
  x1: a,
  x2: b,
  x3: c,
  x4: d,
) -> e

sprintf4(fmt, x1, x2, x3, x4) takes a formatting specification fmt and four values x1, x2, x3, and x4, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf5(
  fmt: Fmt(String, fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> f),
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
) -> f

sprintf5(fmt, x1, x2, x3, x4, x5) takes a formatting specification fmt and five values x1, x2, x3, x4, and x5, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf6(
  fmt: Fmt(
    String,
    fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> fn(f) -> g,
  ),
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
) -> g

sprintf6(fmt, x1, x2, x3, x4, x5, x6) takes a formatting specification fmt and six values x1, x2, x3, x4, x5, and x6, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf7(
  fmt: Fmt(
    String,
    fn(a) ->
      fn(b) -> fn(c) -> fn(d) -> fn(e) -> fn(f) -> fn(g) -> h,
  ),
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
  x7: g,
) -> h

sprintf7(fmt, x1, x2, x3, x4, x5, x6, x7) takes a formatting specification fmt and seven values x1, x2, x3, x4, x5, x6, and x7, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf8(
  fmt: Fmt(
    String,
    fn(a) ->
      fn(b) ->
        fn(c) -> fn(d) -> fn(e) -> fn(f) -> fn(g) -> fn(h) -> i,
  ),
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
  x7: g,
  x8: h,
) -> i

sprintf8(fmt, x1, x2, x3, x4, x5, x6, x7, x8) takes a formatting specification fmt and eight values x1, x2, x3, x4, x5, x6, x7, and x8, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn sprintf9(
  fmt: Fmt(
    String,
    fn(a) ->
      fn(b) ->
        fn(c) ->
          fn(d) -> fn(e) -> fn(f) -> fn(g) -> fn(h) -> fn(i) -> j,
  ),
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
  x7: g,
  x8: h,
  x9: i,
) -> j

sprintf9(fmt, x1, x2, x3, x4, x5, x6, x7, x8, x9) takes a formatting specification fmt and nine values x1, x2, x3, x4, x5, x6, x7, x8, and x9, and returns the specified string with the appropriate placeholders filled by the given values.

pub fn string() -> Fmt(a, fn(String) -> a)

string() returns a format specification for a string value. You could think of this as a placeholder that must be filled with a value of the type String.

pub fn uncurry2(f: fn(a) -> fn(b) -> c, x1: a, x2: b) -> c

uncurry2(f, x1, x2) takes a curried function f and two arguments x1 and x2, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

pub fn uncurry3(
  f: fn(a) -> fn(b) -> fn(c) -> d,
  x1: a,
  x2: b,
  x3: c,
) -> d

uncurry3(f, x1, x2, x3) takes a curried function f and three arguments x1, x2, and x3, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

pub fn uncurry4(
  f: fn(a) -> fn(b) -> fn(c) -> fn(d) -> e,
  x1: a,
  x2: b,
  x3: c,
  x4: d,
) -> e

uncurry4(f, x1, x2, x3, x4) takes a curried function f and four arguments x1, x2, x3, and x4, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

pub fn uncurry5(
  f: fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> f,
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
) -> f

uncurry5(f, x1, x2, x3, x4, x5) takes a curried function f and five arguments x1, x2, x3, x4, and x5, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

pub fn uncurry6(
  f: fn(a) -> fn(b) -> fn(c) -> fn(d) -> fn(e) -> fn(f) -> g,
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
) -> g

uncurry6(f, x1, x2, x3, x4, x5, x6) takes a curried function f and six arguments x1, x2, x3, x4, x5, and x6, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

pub fn uncurry7(
  f: fn(a) ->
    fn(b) -> fn(c) -> fn(d) -> fn(e) -> fn(f) -> fn(g) -> h,
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
  x7: g,
) -> h

uncurry7(f, x1, x2, x3, x4, x5, x6, x7) takes a curried function f and seven arguments x1, x2, x3, x4, x5, x6, and x7, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

pub fn uncurry8(
  f: fn(a) ->
    fn(b) ->
      fn(c) -> fn(d) -> fn(e) -> fn(f) -> fn(g) -> fn(h) -> i,
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
  x7: g,
  x8: h,
) -> i

uncurry8(f, x1, x2, x3, x4, x5, x6, x7, x8) takes a curried function f and eight arguments x1, x2, x3, x4, x5, x6, x7, and x8, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

pub fn uncurry9(
  f: fn(a) ->
    fn(b) ->
      fn(c) ->
        fn(d) -> fn(e) -> fn(f) -> fn(g) -> fn(h) -> fn(i) -> j,
  x1: a,
  x2: b,
  x3: c,
  x4: d,
  x5: e,
  x6: f,
  x7: g,
  x8: h,
  x9: i,
) -> j

uncurry9(f, x1, x2, x3, x4, x5, x6, x7, x8, x9) takes a curried function f and nine arguments x1, x2, x3, x4, x5, x6, x7, x8, and x9, and returns the result of applying the function f to the arguments.

This is useful for continuing a pipeline when using the curried version of sprintf.

Search Document