<commit_before>package org.reactress
package algebra






/** An injective function between values of two types `T` and `S`.
 *
 *  An injection maps every element of type `T` into exactly one
 *  element of type `S`, and can map some elements of type `S` into
 *  one element of type `T`.
 *  It is a function and its partial inverse bundled together.
 *
 *  For example, a mapping from natural numbers to twice their value
 *  forms an injection `1 -> 2`, `2 -> 4`, `3 -> 6` and so on.
 *  The inverse is not defined for every natural number --
 *  `2` is mapped to `1`, but `3` is not mapped to anything.
 *
 *  Additionally, it has the property that `b.inv(b.apply(x)) == x`.
 *  If `b.inv` is defined for `x`, then `b.apply(b.inv(x)) == x`.
 *
 *  @param T      the source type `T`
 *  @param S      the target type `S`
 */
trait Injection[T, S] extends (T => S) {
  /** Maps an element of type `T` to `S`.
   */
  def apply(t: T): S

  /** Checks if value `s` of type `S` maps back to `T`.
   */
  def isDefinedAt(s: S): Boolean

  /** Inverse mapping from `S` to `T`.
   */
  def inv(s: S): T

  /** Returns a partial inverse.
   */
  def inverse: PartialFunction[S, T]
}


object Inverse {

  def apply[T, S](f: T => S, i: PartialFunction[S, T]) = new Injection[T, S] {
    def apply(t: T): S = f(t)
    def isDefinedAt(s: S) = i.isDefinedAt(s)
    def inv(s: S): T = i(s)
    def inverse = i
  }

}<commit_msg>Renamed injection companion to a proper name.<commit_after>package org.reactress
package algebra






/** An injective function between values of two types `T` and `S`.
 *
 *  An injection maps every element of type `T` into exactly one
 *  element of type `S`, and can map some elements of type `S` into
 *  one element of type `T`.
 *  It is a function and its partial inverse bundled together.
 *
 *  For example, a mapping from natural numbers to twice their value
 *  forms an injection `1 -> 2`, `2 -> 4`, `3 -> 6` and so on.
 *  The inverse is not defined for every natural number --
 *  `2` is mapped to `1`, but `3` is not mapped to anything.
 *
 *  Additionally, it has the property that `b.inv(b.apply(x)) == x`.
 *  If `b.inv` is defined for `x`, then `b.apply(b.inv(x)) == x`.
 *
 *  @param T      the source type `T`
 *  @param S      the target type `S`
 */
trait Injection[T, S] extends (T => S) {
  /** Maps an element of type `T` to `S`.
   */
  def apply(t: T): S

  /** Checks if value `s` of type `S` maps back to `T`.
   */
  def isDefinedAt(s: S): Boolean

  /** Inverse mapping from `S` to `T`.
   */
  def inv(s: S): T

  /** Returns a partial inverse.
   */
  def inverse: PartialFunction[S, T]
}


object Injection {

  def apply[T, S](f: T => S, i: PartialFunction[S, T]) = new Injection[T, S] {
    def apply(t: T): S = f(t)
    def isDefinedAt(s: S) = i.isDefinedAt(s)
    def inv(s: S): T = i(s)
    def inverse = i
  }

}
{'fraction_non_alphanumeric': 0.14509394572025053, 'fraction_numerical': 0.006263048016701462, 'mean_word_length': 2.6953727506426737, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1081620', 'n_tokens_mistral': 1033, 'n_tokens_neox': 1002, 'n_words': 422}