Effection
1 Order
1.1 Orderings
ordering-lt
ordering-eq
ordering-gt
ordering-private?
dex-result?
cline-result?
make-ordering-private-lt
make-ordering-private-gt
1.2 Names, Dexes, and Dexables
name?
dex?
in-dex?
name-of
compare-by-dex
dexable
valid-dexable?
dexableof
compare-dexables
name-of-dexable
dex-name
dex-dex
dex-give-up
dex-default
dex-opaque
dex-by-own-method
dex-fix
dex-struct-by-field-position
dex-struct
1.3 Clines
cline?
get-dex-from-cline
in-cline?
compare-by-cline
dex-cline
cline-by-dex
cline-give-up
cline-default
cline-opaque
cline-by-own-method
cline-fix
cline-struct-by-field-position
cline-struct
1.4 Merges and Fuses
merge?
fuse?
call-merge
call-fuse
dex-merge
dex-fuse
merge-by-dex
fuse-by-merge
merge-opaque
fuse-opaque
merge-by-own-method
fuse-by-own-method
merge-fix
fuse-fix
merge-struct-by-field-position
fuse-struct-by-field-position
merge-struct
fuse-struct
1.5 Tables
table?
table-get
table-empty
table-shadow
table-map-fuse
table-sort
dex-table
merge-table
fuse-table
1.6 Fusable Functions
fusable-function?
make-fusable-function
fuse-fusable-function
1.7 Operations for Other Data Types and Derived Operations
dex-immutable-string
cline-immutable-string
dex-exact-rational
cline-exact-rational
fuse-exact-rational-by-plus
fuse-exact-rational-by-times
assocs->table-if-mutually-unique
eq-by-dex?
7.1

Effection

Effection is a library for managing side effects in Racket. It supports a certain programming style that’s almost pure, but which also has the ability to introduce handlers for custom side effects.

The notion of purity Effection uses is chosen deliberately, and it’s meant to facilitate commutative extensibility mechanisms by way of quasi-deterministic concurrency.

The notions of side effect in Effection are also chosen according to elaborate reasoning, although at this point they’re very experimental. The most remarkable feature of Effection’s side effects is that the dynamically scoped regions they’re observable in can have dynamically scoped holes inside, which for instance can take undesired side effects out of scope for controlled periods of time.

This is all a work in progress. The only pieces of Effection that are fully implemented at this point are some pure utilities that will come in handy for commutatively merging values.

For a more thorough overview of Effection’s goals, see the readme.

    1 Order

      1.1 Orderings

      1.2 Names, Dexes, and Dexables

      1.3 Clines

      1.4 Merges and Fuses

      1.5 Tables

      1.6 Fusable Functions

      1.7 Operations for Other Data Types and Derived Operations

1 Order

 (require effection/order/base) package: effection-lib

A “cline” is based on a total ordering on values in its domain, or in other words a binary relation that is reflexive, transitive, and antisymmetric. Its antisymmetry is as fine-grained as possible: If any two values in a cline’s domain are related by that cline in both directions, only Effection-unsafe code will be able to distinguish the two values.

However, a cline does not merely expose this total ordering. Within the cline’s domain, there may be equivalence classes of values for which every two nonequal values will not have their relative order exposed to Effection-safe code. When Effection-safe code uses compare-by-cline to compare two values by a cline, it can get several results:

The “secretly precedes” and “secretly follows” cases are indistinguishable to Effection-safe code.

A “dex” is like a cline, but it never results in the “candidly precedes” and “candidly follows” cases. Thus, a dex is useful as a kind of equality test.

All the exports of effection/order/base are also exported by effection/order.

1.1 Orderings

struct

(struct ordering-lt ())

A struct that represents the result of a comparison where the first value turned out to be candidly strictly less than the second value.

For the purposes of Effection-unsafe Racket code, every two ordering-lt values are equal?.

struct

(struct ordering-eq ())

A struct that represents the result of a comparison where the first value turned out to be equal to the second value.

For the purposes of Effection-unsafe Racket code, every two ordering-eq values are equal?.

struct

(struct ordering-gt ())

A struct that represents the result of a comparison where the first value turned out to be candidly strictly greater than the second value.

For the purposes of Effection-unsafe Racket code, every two ordering-gt values are equal?.

procedure

(ordering-private? x)  boolean?

  x : any/c
Returns whether the given value is an opaque value that represents the result of a comparison where the first value turned out to be secretly strictly less than or secretly strictly greater than the second value.

procedure

(dex-result? x)  boolean?

  x : any/c
Returns whether the given value is a possible result for a dex (something that satisfies either ordering-eq? or ordering-private?).

procedure

(cline-result? x)  boolean?

  x : any/c
Returns whether the given value is a possible result for a dex (something that satisfies ordering-lt?, dex-result?, or ordering-gt?).

Returns a value that represents the result of a comparison where the first value turned out to be secretly strictly less than the second value.

Returns a value that represents the result of a comparison where the first value turned out to be secretly strictly greater than the second value.

1.2 Names, Dexes, and Dexables

procedure

(name? x)  boolean?

  x : any/c
Returns whether the given value is a name. In Effection, a "name" is something like a partial application of comparison by a dex. Any value can be converted to a name using name-of if any dex for that value is at hand (and it always converts to the same name regardless of which dex is chosen), and names themselves can be compared using (dex-name).

procedure

(dex? x)  boolean?

  x : any/c
Returns whether the given value is a dex.

procedure

(in-dex? dex x)  boolean?

  dex : dex?
  x : any/c
Given a dex and a value, returns whether the value belongs to the dex’s domain.

procedure

(name-of dex x)  (maybe/c name?)

  dex : dex?
  x : any/c
Given a dex and a value, returns a just of a name that the value can be compared by, if the value belongs to the dex’s domain; otherwise returns a nothing.

procedure

(compare-by-dex dex a b)  (maybe/c dex-result?)

  dex : dex?
  a : any/c
  b : any/c
Given a dex and two values, compares those values according to the dex. The result is (nothing) if either value is outside the dex’s domain.

struct

(struct dexable (dex value))

  dex : any/c
  value : any/c
A struct that pairs a value with a dex that it purportedly belongs to. If dex actually is a dex and value actually does belong to its domain, this is considered well-formed.

procedure

(valid-dexable? x)  boolean?

  x : any/c
Returns whether the given value is a well-formed dexable.

procedure

(dexableof c)  contract?

  c : contract?
Returns a contract that recognizes a well-formed dexable and additionally imposes the given contract on its dexable-value.

procedure

(compare-dexables a b)  (maybe/c dex-result?)

  a : valid-dexable?
  b : valid-dexable?
Compares the two given well-formed dexable values to see if they have the same dexable-dex and the same dexable-value. If they have the same dex, this returns a just of a dex-result?; otherwise, this returns (nothing).

The dex’s compare-by-dex behavior is called as a tail call when comparing the values.

procedure

(name-of-dexable x)  name?

  x : valid-dexable?
Given a well-formed dexable value, returns a name the contained value can be compared by.

This is a convenience layer over name-of.

procedure

(dex-name)  dex?

Returns a dex that compares names.

procedure

(dex-dex)  dex?

Returns a dex that compares dexes.

All presently existing dexes allow this comparison to be fine-grained enough that it trivializes their equational theory. For instance, (dex-default (dex-give-up) (dex-give-up)) and (dex-give-up) can be distinguished this way despite otherwise having equivalent behavior.

procedure

(dex-give-up)  dex?

Returns a dex over an empty domain.

procedure

(dex-default dex-for-trying-first    
  dex-for-trying-second)  dex?
  dex-for-trying-first : dex?
  dex-for-trying-second : dex?
Given two dexes, returns a dex over the union of their domains.

For the sake of nontermination, error, and performance concerns, this attempts to compute the result using dex-for-trying-first before it moves on to dex-for-trying-second.

The invocation of dex-for-trying-second is a tail call.

When compared by (dex-dex), all dex-default values are ordering-eq if their dex-for-trying-first values are and their dex-for-trying-second values are.

procedure

(dex-opaque name dex)  dex?

  name : name?
  dex : dex?
Given a name and a dex, returns another dex that behaves like the given one but is not equal to it.

When compared by (dex-dex), all dex-opaque values are ordering-eq if their name values are and their dex values are.

procedure

(dex-by-own-method dexable-get-method)  dex?

  dexable-get-method : (dexableof (-> any/c (maybe/c dex?)))
Given a dexable function, returns a dex that works by invoking that function with each value to get (just dex) or (nothing), verifying that the two dex values are the same, and then proceeding to tail-call that dex value.

When compared by (dex-dex), all dex-by-own-method values are ordering-eq if their dexable-get-method values’ dexes and values are.

procedure

(dex-fix dexable-unwrap)  dex?

  dexable-unwrap : (dexableof (-> dex? dex?))
Given a dexable function, returns a dex that works by passing itself to the function and then tail-calling the resulting dex.

When compared by (dex-dex), all dex-fix values are ordering-eq if their dexable-unwrap values’ dexes and values are.

syntax

(dex-struct-by-field-position struct-id
  [field-position-nat dex-expr]
  ...)
 
  dex-expr : dex?
Returns a dex that compares instances of the structure type named by struct-id, and whose field values can be compared by the dexes produced by the dex-expr expressions.

Each field-position-nat must be a distinct number indicating which field should be checked by the associated dex, and there must be an entry for every field.

For the sake of nontermination, error, and performance concerns, this dex computes by attempting the given dexes in the order they appear in this call. If a dex before the last one determines a non-ordering-eq result, the following dexes are only checked to be sure their domains contain the respective field values. Otherwise, the last dex, if any, is attempted as a tail call.

A struct type is only permitted for struct-id if it’s fully immutable and has no super-type.

When compared by (dex-dex), all dex-struct-by-field-position values are ordering-eq if they’re for the same structure type descriptor, if they have field-position-nat values in the same sequence, and if their dex-expr values are ordering-eq.

syntax

(dex-struct struct-id dex-expr ...)

 
  dex-expr : dex?
Returns a dex that compares instances of the structure type named by struct-id, and whose field values can be compared by the dexes produced by the dex-expr expressions.

For the sake of nontermination, error, and performance concerns, this dex computes by attempting the given dexes in the order they appear in this call. The last dex, if any, is attempted as a tail call.

A struct type is only permitted for struct-id if it’s fully immutable and has no super-type.

When compared by (dex-dex), each dex-struct value is ordering-eq to the equivalent dex-struct-by-field-position value.

1.3 Clines

procedure

(cline? x)  boolean?

  x : any/c
Returns whether the given value is a cline.

procedure

(get-dex-from-cline cline)  dex?

  cline : cline?
Given a cline, returns a dex over the same domain.

procedure

(in-cline? cline x)  boolean?

  cline : cline?
  x : any/c
Given a cline and a value, returns whether the value belongs to the cline’s domain.

procedure

(compare-by-cline cline a b)  (maybe/c cline-result?)

  cline : cline?
  a : any/c
  b : any/c
Given a cline and two values, compares those values according to the cline. The result is (nothing) if either value is outside the cline’s domain.

procedure

(dex-cline)  dex?

Returns a dex that compares clines.

All presently existing clines allow this comparison to be fine-grained enough that it trivializes their equational theory. For instance, (cline-default (cline-give-up) (cline-give-up)) and (cline-give-up) can be distinguished this way despite otherwise having equivalent behavior.

procedure

(cline-by-dex dex)  cline?

  dex : dex?
Returns a cline that compares values by tail-calling the given dex. Since the dex never returns the "candidly precedes" or "candidly follows" results, this cline doesn’t either.

When compared by (dex-cline), all cline-by-dex values are ordering-eq if their dexes are.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to the original dex.

procedure

(cline-give-up)  cline?

Returns a cline over an empty domain.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to (dex-give-up).

procedure

(cline-default cline-for-trying-first    
  cline-for-trying-second)  cline?
  cline-for-trying-first : cline?
  cline-for-trying-second : cline?
Given two clines, returns a cline over the union of their domains. The resulting cline’s ascending order consists of the first cline’s ascending order in its domain, followed by the second cline’s ascending order outside the first cline’s domain.

For the sake of nontermination, error, and performance concerns, this attempts to compute the result using cline-for-trying-first before it moves on to cline-for-trying-second.

The invocation of cline-for-trying-second is a tail call.

When compared by (dex-cline), all cline-default values are ordering-eq if their cline-for-trying-first values are and their cline-for-trying-second values are.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to the similarly constructed dex-default.

procedure

(cline-opaque name cline)  cline?

  name : name?
  cline : cline?
Given a name and a cline, returns another cline that behaves like the given one but is not equal to it.

When compared by (dex-cline), all cline-opaque values are ordering-eq if their name values are and their cline values are.

procedure

(cline-by-own-method dexable-get-method)  cline?

  dexable-get-method : (dexableof (-> any/c (maybe/c cline?)))
Given a dexable function, returns a cline that works by invoking that function with each value to get (just cline) or (nothing), verifying that the two cline values are the same, and then proceeding to tail-call that value.

When compared by (dex-cline), all cline-by-own-method values are ordering-eq if their dexable-get-method values’ dexes and values are.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to another dex only if that dex was obtained the same way from a cline ordering-eq to this one.

procedure

(cline-fix dexable-unwrap)  cline?

  dexable-unwrap : (dexableof (-> cline? cline?))
Given a dexable function, returns a cline that works by passing itself to the function and then tail-calling the resulting cline.

When compared by (dex-cline), all cline-fix values are ordering-eq if their dexable-unwrap values’ dexes and values are.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to another dex only if that dex was obtained the same way from a cline ordering-eq to this one.

syntax

(cline-struct-by-field-position struct-id
  [field-position-nat cline-expr]
  ...)
 
  cline-expr : cline?
Returns a cline that compares instances of the structure type named by struct-id, and whose field values can be compared by the clines produced by the cline-expr expressions. The comparison is lexicographic, with the most significant comparisons being the cline-expr values that appear earliest in this call.

Each field-position-nat must be a distinct number indicating which field should be checked by the associated cline, and there must be an entry for every field.

For the sake of nontermination, error, and performance concerns, this cline computes by attempting the given clines in the order they appear in this call. The last cline, if any, is attempted as a tail call.

A struct type is only permitted for struct-id if it’s fully immutable and has no super-type.

When compared by (dex-cline), all cline-struct-by-field-position values are ordering-eq if they’re for the same structure type descriptor, if they have field-position-nat values in the same sequence, and if their cline-expr values are ordering-eq.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to the similarly constructed dex-struct-by-field-position.

syntax

(cline-struct struct-id cline-expr ...)

 
  cline-expr : cline?
Returns a cline that compares instances of the structure type named by struct-id, and whose field values can be compared by the clines produced by the cline-expr expressions. The comparison is lexicographic, with the most significant comparisons being the cline-expr values that appear earliest in this call.

For the sake of nontermination, error, and performance concerns, this cline computes by attempting the given clines in the order they appear in this call. If a cline before the last one determines a non-ordering-eq result, the following clines are only checked to be sure their domains contain the respective field values. Otherwise, the last cline, if any, is attempted as a tail call.

A struct type is only permitted for struct-id if it’s fully immutable and has no super-type.

When compared by (dex-cline), each cline-struct value is ordering-eq to the equivalent cline-struct-by-field-position value.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to the similarly constructed dex-struct.

1.4 Merges and Fuses

Effection offers a non-exhaustive but extensive selection of "merges" and "fuses." These are values which can be compared for equality with like values (using (dex-merge) and (dex-fuse)), and they represent operations of two arguments (invocable using call-merge and call-fuse).

Merges represent operations that are commutative, associative, and idempotent, or in other words exactly the kind of operation that can operate on a (nonempty and finite) unordered set of inputs.

Fuses represent operations that are commutative and associative (and not necessarily idempotent). A fuse is ideal for operating on a (nonempty and finite) unordered multiset of inputs.

The idempotence of a merge operation is such enough that if the two inputs to the merge are order-eq by any dex, the result will be order-eq to them both by the same dex.

procedure

(merge? x)  boolean?

  x : any/c

procedure

(fuse? x)  boolean?

  x : any/c
Returns whether the given value is a merge/fuse.

procedure

(call-merge merge a b)  maybe?

  merge : merge?
  a : any/c
  b : any/c

procedure

(call-fuse fuse a b)  maybe?

  fuse : fuse?
  a : any/c
  b : any/c
Given a merge/fuse and two values, combines those values according to the merge/fuse. The result is (nothing) if either value is outside the merge’s/fuse’s domain. Otherwise, the result is (just value) for some value that’s also in the domain.

For call-merge, if there is any dex for which the input values are ordering-eq, then the result will be ordering-eq to them both.

procedure

(dex-merge)  dex?

procedure

(dex-fuse)  dex?

Returns a dex that compares merges/fuses.

procedure

(merge-by-dex dex)  merge?

  dex : dex?
Returns a merge that merges any values that are already ordering-eq according the given dex. The result of the merge is ordering-eq to both of the inputs.

When compared by (dex-merge), all merge-by-dex values are ordering-eq if their dexes are.

procedure

(fuse-by-merge merge)  fuse?

  merge : merge?
Returns a fuse that fuses values by merging them using the given merge.

When compared by (dex-fuse), all fuse-by-merge values are ordering-eq if their merges are.

procedure

(merge-opaque name merge)  merge?

  name : name?
  merge : merge?

procedure

(fuse-opaque name fuse)  fuse?

  name : name?
  fuse : fuse?
Given a name and a merge/fuse, returns another merge/fuse that behaves like the given one but is not equal to it.

When compared by (dex-merge)/(dex-fuse), all merge-opaque/fuse-opaque values are ordering-eq if their name values are and their merge/fuse values are.

procedure

(merge-by-own-method dexable-get-method)  merge?

  dexable-get-method : (dexableof (-> any/c (maybe/c merge?)))

procedure

(fuse-by-own-method dexable-get-method)  fuse?

  dexable-get-method : (dexableof (-> any/c (maybe/c fuse?)))
Given a dexable function, returns a merge/fuse that works by invoking that function with each value to get (just method) or (nothing), verifying that the two method values are the same, and invoking that merge/fuse value to get a result of (just result) or (nothing). If the result is (just result), this does a final check before returning it: It invokes the method-getting function on the result to verify that it obtains the same method value that was obtained from the inputs. This ensures that the operation is associative.

When compared by (dex-merge)/(dex-fuse), all merge-by-own-method/fuse-by-own-method values are ordering-eq if their dexable-get-method values’ dexes and values are.

procedure

(merge-fix dexable-unwrap)  merge?

  dexable-unwrap : (dexableof (-> merge? merge?))

procedure

(fuse-fix dexable-unwrap)  fuse?

  dexable-unwrap : (dexableof (-> fuse? fuse?))
Given a dexable function, returns a merge/fuse that works by passing itself to the function and then tail-calling the resulting merge/fuse.

When compared by (dex-merge)/(dex-fuse), all merge-fix/fuse-fix values are ordering-eq if their dexable-unwrap values’ dexes and values are.

syntax

(merge-struct-by-field-position struct-id
  [field-position-nat field-method-expr]
  ...)
 
  field-method-expr : merge?

syntax

(fuse-struct-by-field-position struct-id
  [field-position-nat fuse-expr]
  ...)
 
  field-method-expr : fuse?
Returns a merge/fuse that combines instances of the structure type named by struct-id, and whose field values can be combined by the merges/fuses produced by the field-method-expr expressions.

Each field-position-nat must be a distinct number indicating which field should be checked by the associated merge/fuse, and there must be an entry for every field.

A struct type is only permitted for struct-id if it’s fully immutable and has no super-type.

When compared by (dex-merge)/(dex-fuse), all merge-struct-by-field-position/fuse-struct-by-field-position values are ordering-eq if they’re for the same structure type descriptor, if they have field-position-nat values in the same sequence, and if their field-method-expr values are ordering-eq.

syntax

(merge-struct struct-id field-method-expr ...)

 
  field-method-expr : merge?

syntax

(fuse-struct struct-id field-method-expr ...)

 
  field-method-expr : fuse?
Returns a merge/fuse that combines instances of the structure type named by struct-id, and whose field values can be combined by the merges/fuses produced by the field-method-expr expressions.

A struct type is only permitted for struct-id if it’s fully immutable and has no super-type.

When compared by (dex-merge)/(dex-fuse), each merge-struct/fuse-struct value is ordering-eq to the equivalent merge-struct-by-field-position/fuse-struct-by-field-position value.

1.5 Tables

Effection’s "tables" are similar to Racket hash tables where all the keys are Effection name values. However, tables are encapsulated in such a way that Effection-safe code will always process the table entries in an order-oblivious way. For instance, an Effection table cannot be converted to a list in general. This makes tables useful for representing orderless sets that cross API boundaries, where the API client should not be able to depend on accidental details of the set representation.

procedure

(table? x)  boolean?

  x : any/c
Returns whether the given value is an Effection table.

procedure

(table-get key table)  maybe?

  key : name?
  table : table?
Returns the value associated with the given name in the given table, if any.

procedure

(table-empty)  table?

Returns an empty table. In this table, the result of table-get for any name is (nothing).

procedure

(table-shadow key maybe-val table)  table?

  key : name?
  maybe-val : maybe?
  table : table?
Returns another table that’s just like the given one, except that the table-get result for the given name is the given maybe? value. That is, this overwrites or removes the value associated with the given name.

procedure

(table-map-fuse table fuse key-to-operand)  maybe?

  table : table?
  fuse : fuse?
  key-to-operand : (-> name? any/c)
Given a table, a fuse, and a function, calls that function with each key of the table, and returns a just containing the fused value of all the function results. If the table is empty or if any function result is outside the fuse’s domain, this returns (nothing) instead.

procedure

(table-sort cline table)  (maybe/c (listof table?))

  cline : cline?
  table : table?
Given a cline and a table, sorts the values of the table by the cline, without determining an order on values that the cline doesn’t determine an order on. This returns (nothing) if any of the values are outside the cline’s domain. Otherwise, it returns a just containing a list of nonempty tables, partitioning the original table’s values in ascending order.

What we mean by partitioning is this: Each entry of the original table appears in one and only one table in the list, and the tables have no other entries.

What we mean by ascending order is this: If the given cline computes that one value of the original table is (ordering-lt) to a second value, then the two values are stored in two different tables, and the first value’s table precedes the second value’s table in the list. Likewise (and equivalently), if a value is (ordering-gt) to a second value, the first occurs after the second in the list of tables.

procedure

(dex-table dex-val)  dex?

  dex-val : dex?
Returns a dex that compares tables, using the given dex to compare each value.

When compared by (dex-dex), all dex-table values are ordering-eq if their dex-val values are.

procedure

(merge-table merge-val)  merge?

  merge-val : merge?

procedure

(fuse-table fuse-val)  fuse?

  fuse-val : fuse?
Returns a merge/fuse that combines tables by collecting all the nonoverlapping entries and combining the overlapping entries using the given merge-val/fuse-val.

When compared by (dex-merge)/(dex-fuse), all merge-table/fuse-table values are ordering-eq if their merge-val/fuse-val values are.

1.6 Fusable Functions

The dex and cline utilities are good for early detection of equality on inductive information, information that we have access to all at once. For coinductive information – that which we may never see the end of – we cannot detect equality early. However, we may still do things based on an assumption of equality and then enforce this assumption as new information comes to light.

Effection uses a dedicated kind of encapsulated data, "fusable functions," for this purpose. As the name implies, fusable functions support a fuse operation. This operation returns a new fusable function right away. Subsequent calls to that function work by calling each of the original functions and fusing their results – a computation which can cause errors if the return values turn out not to be as fusable as expected. We can use those errors to enforce our equality assumptions on the fly.

Effections’s dexes and clines can’t do this kind of delayed enforcement because they only compute simple values like (ordering-lt).

It’s arguable whether Effection’s merges could do this. The property that sets apart a merge from a fuse is that a merge must be idempotent; the result of merging a value with itself must be indistinguishable from the original value. When we fuse a fusable function with itself, we end up with a function that does at least double the amount of computation, so in practice, the original and the fusion will not be indistinguishable. Because of this, Effection’s fusable functions only come with a fuse operation, not a merge operation.

An Effection fusable-function? is also a procedure? value. It can be invoked just like any other Racket procedure.

There is currently no way to make a fusable function that performs a tail call. This property wouldn’t be preserved by fuse-fusable-function anyway.

procedure

(fusable-function? x)  boolean?

  x : any/c
Returns whether the given value is an Effection fusable function value.

procedure

(make-fusable-function proc)  fusable-function?

  proc : (-> any/c any/c)
Returns a fusable function that behaves like the given single-input, single-output function.

procedure

(fuse-fusable-function dexable-arg-to-method)  fuse?

  dexable-arg-to-method : (dexableof (-> any/c fuse?))
Given dexable-arg-to-method as a dexable function, returns a fuse that combines fusable functions. The combined fusable function works by calling the dexable-arg-to-method function to get a fuse, calling both of the originally fused functions to get each of their results, and fusing the results by that fuse. If the results turn out not to be in the fuse’s domain, this causes an error.

When compared by (dex-dex), all fuse-fusable-function values are ordering-eq if their dexable-arg-to-method values’ dexes and values are.

1.7 Operations for Other Data Types and Derived Operations

 (require effection/order) package: effection-lib

The effection/order module exports all the definitions of effection/order/base plus the definitions below.

procedure

(dex-immutable-string)  dex?

Returns a dex that compares immutable strings.

procedure

(cline-immutable-string)  cline?

Returns a cline that compares immutable strings by their string<? ordering.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to (dex-immutable-string).

procedure

(dex-exact-rational)  dex?

Returns a dex that compares exact rational numbers.

procedure

(cline-exact-rational)  cline?

Returns a cline that compares exact rational numbers by their < ordering.

When the dex obtained from this cline using get-dex-from-cline is compared by (dex-dex), it is ordering-eq to (dex-exact-rational).

procedure

(fuse-exact-rational-by-plus)  fuse?

Returns a fuse that fuses exact rational numbers using +.

procedure

(fuse-exact-rational-by-times)  fuse?

Returns a fuse that fuses exact rational numbers using *.

procedure

(assocs->table-if-mutually-unique assocs)  (maybe/c table?)

  assocs : (listof (cons/c name? any/c))
Given an association list, returns a just of a table with the same entries if the keys are mutually unique; otherwise returns (nothing).

This is a procedure that is convenient for two purposes: It’s useful for detecting duplicates in a list of names, and it’s useful for constructing tables. These purposes often coincide, since data structures which contain mutually unique names are often good candidates for converting to tables.

procedure

(eq-by-dex? dex a b)  boolean?

  dex : dex?
  a : any/c
  b : any/c
Given a dex and two values which must be in the dex’s domain, computes whether those values are ordering-eq according to the dex.