
com.jnape.palatable.lambda.adt.hlist.Index Maven / Gradle / Ivy
package com.jnape.palatable.lambda.adt.hlist;
import com.jnape.palatable.lambda.adt.hlist.HList.HCons;
/**
* HList indexes representing a value at arbitrary depth in some compatible HList. HList compatibility requires
* identical element types up to and including the target element, but thereafter is unconstrained in length and element
* type.
*
* @param the target element type
* @param type of compatible HList
*/
public abstract class Index> {
private Index() {
}
/**
* Nest this index deeper by one element.
*
* @param the type of the preceding element
* @return an index at the same Target, nested one level deep
*/
public final Index> after() {
return new N<>(this);
}
/**
* Retrieve the value at this index in hList.
*
* @param hList the hList
* @return the value at this index
*/
public abstract Target get(TargetList hList);
/**
* Set a new value of the same type at this index in an {@link HList}.
*
* @param newElement the new value
* @param hList the HList
* @param the inferred tail type of the HList
* @return the updated HList
*/
public abstract L set(Target newElement, L hList);
/**
* Create a root index for a head value of type Target
.
*
* @param the type of the value to get
* @return the root index
*/
public static Index> index() {
return Z.instance();
}
private static final class Z extends Index> {
private static final Z> INSTANCE = new Z<>();
@Override
public Target get(HCons hList) {
return hList.head();
}
@Override
@SuppressWarnings("unchecked")
public > L set(Target newElement, L hList) {
return (L) hList.tail().cons(newElement);
}
@SuppressWarnings("unchecked")
public static Z instance() {
return (Z) INSTANCE;
}
}
private static final class N, PreviousIndex extends Index> extends Index> {
private final PreviousIndex previousIndex;
private N(PreviousIndex previousIndex) {
this.previousIndex = previousIndex;
}
@Override
public Target get(HCons hList) {
return previousIndex.get(hList.tail());
}
@Override
@SuppressWarnings("unchecked")
public > L set(Target newElement, L hList) {
return (L) previousIndex.set(newElement, hList.tail()).cons(hList.head());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy