lfe_types(7)

πŸ“¦ version 2.2.0, in alpine 3.24, nixos 26.05, nixpkgs unstable

πŸ’– NAME πŸ’–

Okay so welcome to lfe_types(7) from the Miscellaneous Information Manual πŸ¦‹ β€” this is the whole vibe for LFE Types and Functions Specifications, and I’m gonna walk you through it bestie, no cap.


✨ TYPES ✨

This is the description of the type syntax, periodt. Here’s the LFE type β†’ Erlang type mapping, and yes every row is important:

  • (any) β†’ any()
  • (none) β†’ none()
  • (atom) β†’ atom()
  • (integer) β†’ integer()
  • (range i1 i2) β†’ I1..I2
  • (float) β†’ float()
  • (bitstring m n) β†’ <<_:M,_:_*N>>
  • (binary) β†’ <<_:0,_:_*8>>
  • (bitstring) β†’ <<_:0,_:_*1>>
  • (nil) β†’ [] %% nil
  • ... β†’ ...
  • (lambda any <type>) β†’ fun((...) -> <type>)
  • (lambda () <type>) β†’ fun(() -> <type>)
  • (lambda (<tlist>) <type>) β†’ fun((<tlist>) -> <type>)
  • (map) β†’ map()
  • #M() β†’ #{}
  • #M(<key> <value> ...) β†’ #{<pairlist>}
  • (tuple) β†’ tuple()
  • #() β†’ {}
  • #(<tlist>) β†’ {<tlist>}
  • (UNION <tlist>) β†’ <type> | <type>

Apart from the predefined types in the Erlang type system, we also have these predefined types which cannot be redefined: UNION, call, lambda and range πŸ‘‘. The usage of bitstring, tuple and map has also been extended.

Note that the type #M() is the empty map and the type #() is the empty tuple πŸŽ€. We can still use the older (map <key valuelist>) and (tuple <tlist>) formats when declaring types for maps and tuples.

The general form of bitstrings is (bitstring m n) which denotes a bitstring which starts with m bits and continues with segments of n bits. (binary) is a short form for a sequence of bytes while (bitstring) is a short form for a sequence of bits. There is currently no short form for an empty binary, (bitstring 0 0) must be used.

πŸŽ€ Type Declarations of User-Defined Types πŸŽ€

(deftype (type-name) type-def)

(defopaque (type-name) type-def)

(deftype (type-name par1 par2) type-def)

(defopaque (type-name par1 par2) type-def)

For unparameterised types the parentheses around the type name are optional. An example:

(deftype foo (tuple 'foo (integer) (list)))

(deftype bar (tuple 'bar (integer) (list)))

🌸 Type Information in Record Declarations 🌸

(defrecord rec (field1 default1 type1) (field2 default2) (field3))

Fields with type annotations MUST give a default value, and fields without type annotations get the default type (any). That’s the rule, bestie πŸ’….


πŸ”₯ SPECIFICATIONS πŸ”₯

🧚 Type specifications of User-Defined Functions 🧚

(defspec (func-name arity) function-spec ...)

where:

function-spec = (arg-type-list ret-type)
function-spec = (arg-type-list ret-type constraint-list)
function-spec = #M(arg-types arg-type-list ret-type ret-type)
function-spec = #M(arg-types arg-type-list ret-type ret-type
                   contraints constraint-list)
arg-type-list = (arg-type ...)
constraint-list = (constraint ...)
constraint = (var var-type)

For multiple types add more function specs. The parentheses around the function name and the arity are optional. For example from the docs:

(defspec foo ([(pos_integer)] (pos_integer)))

(defspec (foo 1)
  ([(pos_integer)] (pos_integer))
  ([(integer)] (integer)))

(defspec (remove-if 2)
  ([(lambda ((any)) (boolean)) (list)] (list)))

Or with constraints:

(defspec id ((X) X ((X (tuple)))))

(defspec (foo 1)
  ([(tuple X (integer))] X ((X (atom))))
  ([(list Y)] Y ((Y (number)))))

(defspec (remove-if 2)
  ([pred (list)] (list) [(pred (lambda ((any)) (boolean)))]))

Note that a constraint variable doesn’t need to start with an upper-case like an Erlang variable, though in some case it may be easier to read.

Note we are using the alternate list form with [ ] instead of parentheses to make it easier to see the function arguments πŸ‘€.

πŸ¦‹ Types and function specifications in the module definition πŸ¦‹

Types can also be defined in the module declaration, for example:

(defmodule this-module
  ...
  (type ((foo-type) (tuple 'foo (integer) (list)))
        ((bar-type) (tuple 'bar (integer) (list))))
  (spec ((foo 1) ([(integer)] (foo-type)))
        ((id 1) ([x] x ((x (tuple))))))
  ...)

🌈 AUTHORS 🌈

Robert Virding.


Okay that’s the whole page, bestie πŸ’– β€” footer vibes: 2021, lfe_types(7). Bye and slay your types! 🫢

πŸ“¦ where this page comes from