public static @NotNull <A, B, C> Function<A, C> compose(final @NotNull Function<? super A, ? extends B> f1, final @NotNull Function<? super B, ? extends C> f2) {
    if (f1 == identity() || f2 == identity()) {
      if (f1 == f2) {
        return identity();
      }
      if (f1 == identity()) {
        //noinspection unchecked
        return (Function<A, C>)f2;
      }
      //noinspection unchecked
      return (Function<A, C>)f1;
    }
    return a -> f2.fun(f1.fun(a));
  }
public static @NotNull <A, B, C> Function<A, C> compose(final @NotNull Function<? super A, ? extends B> f1, final @NotNull Function<? super B, ? extends C> f2)