Created
February 25, 2018 22:01
-
-
Save jnape/795edf6446416966b5f68daa355d426e to your computer and use it in GitHub Desktop.
Mapping the slots of an HList
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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