// @ts-nocheck
import { it, assert } from 'folktest'
import { IO, List, Option, Reader, Result, Some } from '../../src/index.js'
import { Applicative, Chain, Ord, Setoid } from '../../src/algebra/interfaces.js'

const Algebra = [Option, Result, List, IO, Reader]

const inc = F => x => F.of(x + 1)
const dbl = F => x => F.of(x * 2)

const impl = i => m => i.implementedBy(m)

export const Tests = [
  it('unit is a left identity', () => {
    Algebra.filter(impl(Setoid, Applicative, Chain)).forEach(algebra => {
      const f = inc(algebra)

      assert(
        algebra.of(1).chain(f).equals(f(1)),
        `${algebra.name} is not a left identity`
      )
    })
  }),

  it('unit is a right identity', () => {
    Algebra.filter(impl(Setoid, Applicative, Chain)).forEach(algebra => {
      const m = algebra.of(1)

      assert(
        m.chain(algebra.of).equals(m),
        `${algebra.name} is not a right identity`
      )
    })
  }),

  it('unit is associative', () => {
    Algebra.filter(impl(Setoid, Applicative, Chain)).forEach(algebra => {
      const a = algebra.of(1)
      const f = inc(algebra)
      const g = dbl(algebra)

      const x = a.chain(f).chain(g)
      const y = a.chain(x => f(x).chain(g))

      assert(x.equals(y), `${algebra.name} is not associative`)
    })
  }),
]