/*!
 * Copyright (c) 2017 by The Funfix Project Developers.
 * Some rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* @flow */

import type { Constructor } from "./kinds"
import { HK, Equiv } from "./kinds"

export interface Functor<F> {
  map<A, B>(fa: HK<F, A>, f: (a: A) => B): HK<F, B>;

  // Implements TypeClass<F>
  static +_funTypeId: string;
  static +_funSupertypeIds: string[];
  static +_funErasure: Functor<any>;
}

export interface FunctorLaws<F> {
  +F: Functor<F>;

  covariantIdentity<A>(fa: HK<F, A>): Equiv<HK<F, A>>;
  covariantComposition<A, B, C>(fa: HK<F, A>, f: (a: A) => B, g: (b: B) => C): Equiv<HK<F, C>>;
}

declare export function functorOf<F>(c: Constructor<F>): Functor<F>;
declare export function functorLawsOf<F>(instance: Functor<F>): FunctorLaws<F>;
