Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Mapping the slots of an HList
package com.jnape.palatable.lambda.adt.hlist;
import com.jnape.palatable.lambda.adt.hlist.HList.HCons;
import com.jnape.palatable.lambda.adt.hlist.HList.HNil;
import java.util.function.Function;
import static com.jnape.palatable.lambda.adt.hlist.HList.cons;
import static com.jnape.palatable.lambda.adt.hlist.HList.nil;
import static com.jnape.palatable.lambda.adt.hlist.HList.singletonHList;
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
public abstract class HListMapper<XS extends HList, YS extends HList> {
private HListMapper() {
}
public abstract <Output extends YS> Output map(XS xs);
public static HListMapper<HNil, HNil> mapHNil() {
return HNilMapper.INSTANCE;
}
public static <A, B, XSTail extends HList, YSTail extends HList, XS extends HCons<A, ? extends XSTail>, YS extends HCons<B, ? extends YSTail>> HListMapper<XS, YS> mapHCons(
Function<? super A, ? extends B> fn,
HListMapper<XSTail, YSTail> tailMapper) {
return new HConsMapper<>(fn, tailMapper);
}
private static final class HConsMapper<A, B, XSTail extends HList, YSTail extends HList, XS extends HCons<A, ? extends XSTail>, YS extends HCons<B, ? extends YSTail>> extends HListMapper<XS, YS> {
private final Function<? super A, ? extends B> fn;
private final HListMapper<XSTail, YSTail> tailMapper;
private HConsMapper(Function<? super A, ? extends B> fn,
HListMapper<XSTail, YSTail> tailMapper) {
this.fn = fn;
this.tailMapper = tailMapper;
}
@Override
@SuppressWarnings("unchecked")
public <Output extends YS> Output map(XS xs) {
return (Output) tailMapper.map(xs.tail()).cons(fn.apply(xs.head()));
}
}
private static final class HNilMapper extends HListMapper<HNil, HNil> {
private static final HNilMapper INSTANCE = new HNilMapper();
private HNilMapper() {
}
@Override
@SuppressWarnings("unchecked")
public <Output extends HNil> Output map(HNil hNil) {
return (Output) hNil;
}
}
public static void main(String[] args) {
Function<String, Integer> parseInt = Integer::parseInt;
//all type-check
Tuple2<Integer, Integer> consToTuple = mapHCons(parseInt, mapHCons(parseInt, mapHNil())).map(cons("1", cons("2", nil())));
HCons<Integer, ? extends HCons<Integer, HNil>> tupleToCons = mapHCons(parseInt, mapHCons(parseInt, mapHNil())).map(tuple("3", "4"));
HCons<Integer, SingletonHList<Integer>> consToConsOfSingleton = mapHCons(parseInt, mapHCons(parseInt, mapHNil())).map(cons("5", cons("6", nil())));
HCons<Integer, SingletonHList<Integer>> consOfSingletonToConsOfSingleton = mapHCons(parseInt, mapHCons(parseInt, mapHNil())).map(cons("7", singletonHList("8")));
HCons<Integer, SingletonHList<Integer>> tupleToConsOfSingleton = mapHCons(parseInt, mapHCons(parseInt, mapHNil())).map(tuple("9", "10"));
Tuple2<Integer, Integer> tupleToTuple = mapHCons(parseInt, mapHCons(parseInt, mapHNil())).map(tuple("11", "12"));
Tuple2<Integer, Integer> reverseConsToTuple = mapHCons(parseInt, mapHCons(parseInt, mapHNil())).map(nil().cons("14").cons("13"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment