Skip to content

Type operations ​

extends? ​

(extends? CHILD PARENT IF ELSE)

Check whether CHILD is a subtype of PARENT.

emacs-lisp
(et (extends? Integer Number 1 0))
;; -> 1
(et (extends? String Number 1 0))
;; -> 0
;; The type variable COULD represent a subtype of Number, or it might not
(et-with-type-variables [T] (et (extends? T Number 1 0)))
;; -> 1 | 0

infer ​

(infer TYPE [GENERICS] PATTERN IF ELSE)

Match type against pattern and determine values for each of the generics. If it matches, then evaluate if with the inferred generics. Otherwise, return else.

emacs-lisp
(et (infer List<Integer> [T] List<T> T Never))
;; -> Integer
(et (infer String [T] List<T> T Never))
;; -> Never

minus ​

(minus A B)

Subtract B from A.

emacs-lisp
(et (minus Number|String Number))
;; -> String
(et (minus List<Integer> Nil))
;; -> (Integer . List<Integer>)

There is not always a perfect answer for type-subtraction. In such cases, minus will always err on the side of keeping the type larger than it should be. See Why upper-bound type-intersection?.

emacs-lisp
(et (minus Number Integer))
;; -> Number

subsect/supersect ​

(subsect A B) / (supersect A B)

Perform lower/upper bound intersection.

emacs-lisp
(et (subsect Integer Positive))
;; -> Never
(et (supersect Integer Positive))
;; -> Integer

(et (supersect (fn1 Integer Integer) (fn1 Number Number)))
;; -> Function<&(Number), Integer>

(et (supersect AnyFn Cons<Any_Any>))
;; -> Function<Never, Any>
(et (supersect AnyFn Cons<Integer_Any>))
;; -> Never
(et (supersect AnyFn Cons<@foo_Any>))
;; -> Never
(et (supersect AnyFn Cons<@lambda_Any>))
;; -> Function<Never, Any>

freshen-deep/freshen-shallow ​

(freshen-deep TYPE) / (freshen-shallow TYPE)

Convert a type to its freshened version.
freshen-deep will recursively freshen every level of the type, like (copy-tree value).
freshen-shallow will only freshen the top-level list, like (apply #'list value)

emacs-lisp
(et (freshen-deep List<List<Integer>>))
;; -> ListFresh<ListFresh<Integer>>
(et (freshen-shallow List<List<Integer>>))
;; -> ListFresh<List<Integer>>
(et (freshen-deep (Cons (Cons 1 2) (Cons 3 4))))
;; -> (ConsFresh (ConsFresh 1 2) (ConsFresh 3 4))
(et (freshen-shallow (Cons (Cons 1 2) (Cons 3 4))))
;; -> (ConsFresh (Cons 1 2) (ConsFresh 3 4))