Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data.Contravariant

Consumers of values: functors that map over their input, not their output.

A Functor produces as and fmap transforms what comes out; a Contravariant consumes as and contramap adapts what goes in. The arrow flips: to turn a consumer of a into a consumer of b, supply a function from b to a. The two carriers here are the archetypes: a Predicate tests a value, a Comparison orders two, and both are adapted to a new type by projecting into the one they already understand, the way a sort by key adapts an ordering on keys to an ordering on records.

contramap takes a pure projection: the carrier stores the function inside a closure, so an effectful projection would smuggle its row into every later call site unseen. Opt-in: not in Base.

Types

Predicate

newtype Predicate(a) = MkPredicate((a) -> Bool)

A test on a single value.

Comparison

newtype Comparison(a) = MkComparison((a, a) -> Int)

A total ordering as a function: negative, zero, or positive, with the same convention as cmp.

Type Classes

Contravariant

class Contravariant(f)
  contramap : ((b) -> a, f(a)) -> f(b)

A functor over input: contramap(id, c) is c, and contramap(g, contramap(h, c)) is contramap(\(x) -> h(g(x)), c) (note the composition flips).

Instances

contravariantPredicate

instance contravariantPredicate : Contravariant(Predicate)

contravariantComparison

instance contravariantComparison : Contravariant(Comparison)

Functions and Values

mk_predicate

mk_predicate : forall a. ((a) -> Bool) -> Data.Contravariant.Predicate(a)

Wrap a test as a Predicate.

run_predicate

run_predicate : forall a. (Data.Contravariant.Predicate(a), a) -> Bool

Apply a Predicate to a value.

let evens = contramap(\(s) -> str_len(s), mk_predicate(\(n) -> n % 2 == 0))
(run_predicate(evens, "hi"), run_predicate(evens, "hey"))
(true, false)

mk_comparison

mk_comparison : forall a. ((a, a) -> Int) -> Data.Contravariant.Comparison(a)

Wrap an ordering function as a Comparison.

run_comparison

run_comparison : forall a. (Data.Contravariant.Comparison(a), a, a) -> Int

Apply a Comparison to two values.

let by_len = contramap(\(s) -> str_len(s), ord_comparison())
(run_comparison(by_len, "hey", "hi"), run_comparison(by_len, "hi", "no"))
(1, 0)

ord_comparison

ord_comparison : forall a. () -> Data.Contravariant.Comparison(a) given Ord(a)

The ordering an Ord instance already carries, as a Comparison value that contramap can then re-aim at another type.