<commit_before>/* @flow */

import { Just, just, nothing } from './src/Maybe'

import type { Maybe } from './src/Maybe'

export {
  compose,
  filtering,
  foldMapOf,
  foldrOf,
  get,
  getter,
  getter as to,
  lens,
  lookup,
  over,
  set,
  sumOf,
  traverseOf,
}

/* Types */

export type Lens<S,T,A,B> =
  <FB: Functor<B>, FT: Functor<T>>
  (f: (pure: Pure_, val: A) => FB) => ((pure: Pure_, obj: S) => FT)

export type Lens_<S,A> = Lens<S,S,A,A>

export type Getting<R,S,A> =
  (f: (pure: Pure_, val: A) => Const<R,A>) => ((pure: Pure_, obj: S) => Const<R,S>)

export type Setting<S,T,A,B> =
  (f: (pure: Pure_, val: A) => Identity<B>) => ((pure: Pure_, obj: S) => Identity<T>)

export type Getter<S,A> =
  <FA: Contravariant<A> & Functor<A>, FS: Contravariant<S> & Functor<S>>
  (f: (pure: Pure_, val: A) => FA) => ((pure: Pure_, obj: S) => FS)

export type Setter<S,T,A,B> =
  <FB: Settable<B>, FT: Settable<T>>
  (f: (pure: Pure_, val: A) => FB) => ((pure: Pure_, obj: S) => FT)

export type Setter_<S,A> = Setter<S,S,A,A>

export type Traversal<S,T,A,B> =
  <FB: Apply<B>, FT: Apply<T>>
  (f: (pure: Pure, val: A) => FB) => ((pure: Pure, obj: S) => FT)

export type Traversal_<S,A> = Traversal<S,S,A,A>

export type Fold<R,S,A> =
  (f: (pure: Pure, val: A) => ApplyConst<R,A>) => ((pure: Pure, obj: S) => ApplyConst<R,S>)


/*
 * Supporting interfaces
 */

// `Pure_` is "pure" for functors - will not be invoked unless further
// constrained to `Pure`
type Pure_ = Function

type Contravariant<A> = {
  contramap<B, FB: Contravariant<B>>(f: (_: B) => A): FB
}

type Settable<A> = Apply<A> & Traversable<A>



/*
 * Algebraic implementations
 */

class Const<R,A> {
  value: R;
  constructor(value: R) {
    this.value = value
  }
  map<B, FB: Const<R,B>>(f: (_: A) => B): FB {
    return (new Const(this.value): any)
  }
  contramap<B, FB: Const<R,B>>(f: (_: B) => A): FB {
    return (new Const(this.value): any)
  }
}

class ApplyConst<R:Monoid,A> extends Const<R,A> {
  ap<T,U, FU: ApplyConst<R,U>>(x: ApplyConst<R,T>): FU {
    return (new ApplyConst(this.value.concat(x.value)): any)
  }
  map<B, FB: ApplyConst<R,B>>(f: (_: A) => B): FB {
    return (new ApplyConst(this.value): any)
  }
  contramap<B, FB: ApplyConst<R,B>>(f: (_: B) => A): FB {
    return (new ApplyConst(this.value): any)
  }
}

class Identity<A> {
  value: A;
  constructor(value: A) {
    this.value = value
  }
  map<B, FB: Identity<B>>(f: (_: A) => B): FB {
    return (new Identity(f(this.value)): any)
  }
  ap<T,U, FU: Identity<U>>(x: Identity<T>): FU {
    var f: any = this.value
    return (new Identity(f(x.value)): any)
  }
  sequence<TA: Traversable<A>, FA: Identity<TA>>(pure: Pure): FA {
    return pure(this)
  }
}

function constant<T, FT: Const<T>>(val: T): FT { return (new Const(val): any) }
function applyConstant<T: Monoid, FT: ApplyConst<T>>(val: T): FT {
  return (new ApplyConst(val): any)
}
function identity<T, FT: Identity<T>>(val: T): FT {
  return (new Identity(val): any)
}

// Ordinary function composition - also works to compose lenses
function compose<A,B,C>(f: (_: B) => C, g: (_: A) => B): (_: A) => C {
  return x => f(g(x))
}

/* lenses */

/*
 * Creates a lens from a getter and setter function.
 */
function lens<S,T,A,B>(
  getter: (obj: S) => A,
  setter: (obj: S, val: B) => T
): Lens<S,T,A,B> {
  return f => (pure, obj) => (
    f(pure, getter(obj)).map(val => setter(obj, val))
  )
}


/* getting */

/*
 * Turns an ordinary function into a getter
 */
function getter<S,A>(getter: (obj: S) => A): Getter<S,A> {
  return f => (pure, obj) => (
    f(pure, getter(obj)).map(_ => obj)
  )
}

/*
 * Given a getter (which is a specialized lens), and data structure, gets
 * a value out of the data structure.
 */
function get<S,A>(getter: Getting<A,S,A>, obj: S): A {
  return getter((_, val) => new Const(val))(constant, obj).value
}


/* setting */

function set<S,T,A,B>(setter: Setting<S,T,A,B>, val: B, obj: S): T {
  return setter((_, __) => new Identity(val))(identity, obj).value
}

function over<S,T,A,B>(setter: Setting<S,T,A,B>, f: (val: A) => B, obj: S): T {
  return setter((_, a) => new Identity(f(a)))(identity, obj).value
}


/* traversing */

function traverseOf<S,T,A,B, FB: Apply<B>, FT: Apply<T>>
  (pure: Pure, l: Traversal<S,T,A,B>, f: (p: Pure, _: A) => FB, obj: S): FT {
  return l(f)(pure, obj)
}

function filtering<S>(predicate: (val: S) => boolean): Traversal_<S,S> {
  return f => (pure, obj) => (
    predicate(obj) ? f(pure, obj).map(id) : pure(obj)
  )
  // TODO: `.map(id)` suppresses a (hopefully unimportant) type error
}


/* folding */

// `First` is one possible Monoid implementation for `Maybe`
class First<A> {
  value: Maybe<A>;
  constructor(value: Maybe<A>) { this.value = value }
  concat<M: First<A>>(other: Monoid): M {
    return ((this.value instanceof Just ? this : other): any)
  }
  empty<M: First<A>>(): M {
    return (new First(nothing): any)
  }
}
function first<A>(val: Maybe<A>): First<A> { return new First(val) }

function foldMapOf<R:Monoid,S,A>(l: Fold<R,S,A>, f: (val: A) => R, mempty: R, obj: S): R {
  var wrapConst = (pure, val) => applyConstant(f(val))
  return l(wrapConst)(_ => applyConstant(mempty), obj).value
}

// `Endo` turns a function into a Monoid
class Endo<A> {
  f: (_: A) => A;
  constructor(f: (_: A) => A) { this.f = f }
  concat<M: Endo<A>>(other: Monoid): M {
    return (new Endo(compose(this.f, (other: any).f)): any)
  }
  empty<M: Endo<A>>(): M {
    return (new Endo(id): any)
  }
}
function endo<A>(f: (_: A) => A): Endo<A> { return new Endo(f) }

function foldrOf<R,S,A>(
  l: Fold<Endo<R>,S,A>, f: (val: A, accum: R) => R, init: R, obj: S
): R {
  var curried = val => accum => f(val, accum)
  return foldMapOf(l, compose(endo, curried), new Endo(id), obj).f(init)
}

function sumOf<S>(l: Fold<Endo<number>,S,number>, obj: S): number {
  return foldrOf(l, (x,y) => x+y, 0, obj)
}

/*
 * `lookup` is like `get`, except that the result might be `undefined`.
 *
 * `get` cannot be used with `Traversal` or `Fold` lenses.
 * In these cases, use `lookup` instead.
 *
 */
function lookup<S,A>(l: Fold<First<A>,S,A>, obj: S): ?A {
  function toMonoid<T>(val: T): First<T> { return first(just(val)) }
  return foldMapOf(l, toMonoid, first(nothing), obj).value.value
}

function id<A>(val: A): A { return val }
<commit_msg>Generalizes `Getting` so that it is compatible with `Fold`<commit_after>/* @flow */

import { Just, just, nothing } from './src/Maybe'

import type { Maybe } from './src/Maybe'

export {
  compose,
  filtering,
  foldMapOf,
  foldrOf,
  get,
  getter,
  getter as to,
  lens,
  lookup,
  over,
  set,
  sumOf,
  traverseOf,
}

/* Types */

export type Lens<S,T,A,B> =
  <FB: Functor<B>, FT: Functor<T>>
  (f: (pure: Pure_, val: A) => FB) => ((pure: Pure_, obj: S) => FT)

export type Lens_<S,A> = Lens<S,S,A,A>

export type Getting<R,S,A> =
  <FA: Const<R,A>, FS: Const<R,S>>
  (f: (pure: Pure_, val: A) => FA) => ((pure: Pure_, obj: S) => FS)

export type Setting<S,T,A,B> =
  (f: (pure: Pure_, val: A) => Identity<B>) => ((pure: Pure_, obj: S) => Identity<T>)

export type Getter<S,A> =
  <FA: Contravariant<A> & Functor<A>, FS: Contravariant<S> & Functor<S>>
  (f: (pure: Pure_, val: A) => FA) => ((pure: Pure_, obj: S) => FS)

export type Setter<S,T,A,B> =
  <FB: Settable<B>, FT: Settable<T>>
  (f: (pure: Pure_, val: A) => FB) => ((pure: Pure_, obj: S) => FT)

export type Setter_<S,A> = Setter<S,S,A,A>

export type Traversal<S,T,A,B> =
  <FB: Apply<B>, FT: Apply<T>>
  (f: (pure: Pure, val: A) => FB) => ((pure: Pure, obj: S) => FT)

export type Traversal_<S,A> = Traversal<S,S,A,A>

export type Fold<R,S,A> =
  (f: (pure: Pure, val: A) => ApplyConst<R,A>) => ((pure: Pure, obj: S) => ApplyConst<R,S>)


/*
 * Supporting interfaces
 */

// `Pure_` is "pure" for functors - will not be invoked unless further
// constrained to `Pure`
type Pure_ = Function

type Contravariant<A> = {
  contramap<B, FB: Contravariant<B>>(f: (_: B) => A): FB
}

type Settable<A> = Apply<A> & Traversable<A>



/*
 * Algebraic implementations
 */

class Const<R,A> {
  value: R;
  constructor(value: R) {
    this.value = value
  }
  map<B, FB: Const<R,B>>(f: (_: A) => B): FB {
    return (new Const(this.value): any)
  }
  contramap<B, FB: Const<R,B>>(f: (_: B) => A): FB {
    return (new Const(this.value): any)
  }
}

class ApplyConst<R:Monoid,A> extends Const<R,A> {
  ap<T,U, FU: ApplyConst<R,U>>(x: ApplyConst<R,T>): FU {
    return (new ApplyConst(this.value.concat(x.value)): any)
  }
  map<B, FB: ApplyConst<R,B>>(f: (_: A) => B): FB {
    return (new ApplyConst(this.value): any)
  }
  contramap<B, FB: ApplyConst<R,B>>(f: (_: B) => A): FB {
    return (new ApplyConst(this.value): any)
  }
}

class Identity<A> {
  value: A;
  constructor(value: A) {
    this.value = value
  }
  map<B, FB: Identity<B>>(f: (_: A) => B): FB {
    return (new Identity(f(this.value)): any)
  }
  ap<T,U, FU: Identity<U>>(x: Identity<T>): FU {
    var f: any = this.value
    return (new Identity(f(x.value)): any)
  }
  sequence<TA: Traversable<A>, FA: Identity<TA>>(pure: Pure): FA {
    return pure(this)
  }
}

function constant<T, FT: Const<T>>(val: T): FT { return (new Const(val): any) }
function applyConstant<T: Monoid, FT: ApplyConst<T>>(val: T): FT {
  return (new ApplyConst(val): any)
}
function identity<T, FT: Identity<T>>(val: T): FT {
  return (new Identity(val): any)
}

// Ordinary function composition - also works to compose lenses
function compose<A,B,C>(f: (_: B) => C, g: (_: A) => B): (_: A) => C {
  return x => f(g(x))
}

/* lenses */

/*
 * Creates a lens from a getter and setter function.
 */
function lens<S,T,A,B>(
  getter: (obj: S) => A,
  setter: (obj: S, val: B) => T
): Lens<S,T,A,B> {
  return f => (pure, obj) => (
    f(pure, getter(obj)).map(val => setter(obj, val))
  )
}


/* getting */

/*
 * Turns an ordinary function into a getter
 */
function getter<S,A>(getter: (obj: S) => A): Getter<S,A> {
  return f => (pure, obj) => (
    f(pure, getter(obj)).map(_ => obj)
  )
}

/*
 * Given a getter (which is a specialized lens), and data structure, gets
 * a value out of the data structure.
 */
function get<S,A>(getter: Getting<A,S,A>, obj: S): A {
  return getter((_, val) => new Const(val))(constant, obj).value
}


/* setting */

function set<S,T,A,B>(setter: Setting<S,T,A,B>, val: B, obj: S): T {
  return setter((_, __) => new Identity(val))(identity, obj).value
}

function over<S,T,A,B>(setter: Setting<S,T,A,B>, f: (val: A) => B, obj: S): T {
  return setter((_, a) => new Identity(f(a)))(identity, obj).value
}


/* traversing */

function traverseOf<S,T,A,B, FB: Apply<B>, FT: Apply<T>>
  (pure: Pure, l: Traversal<S,T,A,B>, f: (p: Pure, _: A) => FB, obj: S): FT {
  return l(f)(pure, obj)
}

function filtering<S>(predicate: (val: S) => boolean): Traversal_<S,S> {
  return f => (pure, obj) => (
    predicate(obj) ? f(pure, obj).map(id) : pure(obj)
  )
  // TODO: `.map(id)` suppresses a (hopefully unimportant) type error
}


/* folding */

// `First` is one possible Monoid implementation for `Maybe`
class First<A> {
  value: Maybe<A>;
  constructor(value: Maybe<A>) { this.value = value }
  concat<M: First<A>>(other: Monoid): M {
    return ((this.value instanceof Just ? this : other): any)
  }
  empty<M: First<A>>(): M {
    return (new First(nothing): any)
  }
}
function first<A>(val: Maybe<A>): First<A> { return new First(val) }

function foldMapOf<R:Monoid,S,A>(l: Fold<R,S,A>, f: (val: A) => R, mempty: R, obj: S): R {
  var wrapConst = (pure, val) => applyConstant(f(val))
  return l(wrapConst)(_ => applyConstant(mempty), obj).value
}

// `Endo` turns a function into a Monoid
class Endo<A> {
  f: (_: A) => A;
  constructor(f: (_: A) => A) { this.f = f }
  concat<M: Endo<A>>(other: Monoid): M {
    return (new Endo(compose(this.f, (other: any).f)): any)
  }
  empty<M: Endo<A>>(): M {
    return (new Endo(id): any)
  }
}
function endo<A>(f: (_: A) => A): Endo<A> { return new Endo(f) }

function foldrOf<R,S,A>(
  l: Fold<Endo<R>,S,A>, f: (val: A, accum: R) => R, init: R, obj: S
): R {
  var curried = val => accum => f(val, accum)
  return foldMapOf(l, compose(endo, curried), new Endo(id), obj).f(init)
}

function sumOf<S>(l: Fold<Endo<number>,S,number>, obj: S): number {
  return foldrOf(l, (x,y) => x+y, 0, obj)
}

/*
 * `lookup` is like `get`, except that the result might be `undefined`.
 *
 * `get` cannot be used with `Traversal` or `Fold` lenses.
 * In these cases, use `lookup` instead.
 *
 */
function lookup<S,A>(l: Fold<First<A>,S,A>, obj: S): ?A {
  function toMonoid<T>(val: T): First<T> { return first(just(val)) }
  return foldMapOf(l, toMonoid, first(nothing), obj).value.value
}

function id<A>(val: A): A { return val }

{'fraction_non_alphanumeric': 0.213018216080402, 'fraction_numerical': 0.000157035175879397, 'mean_word_length': 3.8046020369671822, 'pattern_counts': {'":': 0, '<': 236, '<?xml version=': 0, '>': 352, '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': '6209559', 'n_tokens_mistral': 5481, 'n_tokens_neox': 5261, 'n_words': 1400}