All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tonivade.purefun.generic.HList Maven / Gradle / Ivy

/*
 * Copyright (c) 2018-2020, Antonio Gabriel Muñoz Conejo 
 * Distributed under the terms of the MIT License
 */
package com.github.tonivade.purefun.generic;

import static com.github.tonivade.purefun.Precondition.checkNonNull;

import java.util.Objects;

import com.github.tonivade.purefun.Equal;
import com.github.tonivade.purefun.Tuple1;
import com.github.tonivade.purefun.Tuple2;
import com.github.tonivade.purefun.Tuple3;
import com.github.tonivade.purefun.Tuple4;
import com.github.tonivade.purefun.Tuple5;
import com.github.tonivade.purefun.type.Option;

public interface HList> {

  int size();

   HCons prepend(E element);

   Option find(Class clazz);

  HListModule getModule();

  default boolean isEmpty() {
    return size() == 0;
  }

  static HNil empty() {
    return HNil.INSTANCE;
  }

  static > HCons cons(E element, L list) {
    return new HCons<>(element, list);
  }

  static  HCons of(A element) {
    return empty().prepend(element);
  }

  static  HCons> of(A element1, B element2) {
    return empty().prepend(element2).prepend(element1);
  }

  static  HCons>> of(A element1, B element2, C element3) {
    return empty().prepend(element3).prepend(element2).prepend(element1);
  }

  static  HCons>>> of(A element1,
                                                                      B element2,
                                                                      C element3,
                                                                      D element4) {
    return empty().prepend(element4).prepend(element3).prepend(element2).prepend(element1);
  }

  static  HCons>>>> of(A element1,
                                                                                   B element2,
                                                                                   C element3,
                                                                                   D element4,
                                                                                   E element5) {
    return empty().prepend(element5).prepend(element4).prepend(element3).prepend(element2).prepend(element1);
  }

  static  HCons from(Tuple1 tuple) {
    return tuple.applyTo(HList::of);
  }

  static  HCons> from(Tuple2 tuple) {
    return tuple.applyTo(HList::of);
  }

  static  HCons>> from(Tuple3 tuple) {
    return tuple.applyTo(HList::of);
  }

  static  HCons>>> from(Tuple4 tuple) {
    return tuple.applyTo(HList::of);
  }

  static  HCons>>>> from(Tuple5 tuple) {
    return tuple.applyTo(HList::of);
  }

  final class HNil implements HList {

    private static final HNil INSTANCE = new HNil();

    private HNil() {}

    @Override
    public int size() {
      return 0;
    }

    @Override
    public  HCons prepend(E element) {
      return cons(element, this);
    }

    @Override
    public  Option find(Class clazz) {
      return Option.none();
    }

    @Override
    public HListModule getModule() {
      throw new UnsupportedOperationException();
    }

    @Override
    public String toString() {
      return "HNil";
    }
  }

  final class HCons> implements HList> {

    private static final Equal> EQUAL = Equal.>of()
        .comparing(HCons::head)
        .comparing(HCons::tail);

    private final H head;
    private final T tail;

    private HCons(H head, T tail) {
      this.head = checkNonNull(head);
      this.tail = checkNonNull(tail);
    }

    public H head() {
      return head;
    }

    public T tail() {
      return tail;
    }

    @Override
    public int size() {
      return 1 + tail.size();
    }

    @Override
    public  HCons> prepend(E element) {
      return cons(element, this);
    }

    @Override
    public  Option find(Class clazz) {
      if (clazz.isInstance(head)) {
        return Option.some(clazz.cast(head));
      }
      return tail.find(clazz);
    }

    @Override
    public HListModule getModule() {
      throw new UnsupportedOperationException();
    }

    @Override
    public int hashCode() {
      return Objects.hash(head, tail);
    }

    @Override
    public boolean equals(Object obj) {
      return EQUAL.applyTo(this, obj);
    }

    @Override
    public String toString() {
      return "HCons(" + head + "," + tail + ")";
    }
  }
}

interface HListModule {}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy