ML / (Sıkı) Java'da Haskell
Bu gerçek bir projeden. Kalıcı değişken veri yapılarını kullanır ve gerekli olmasa bile özyinelemeyi kullanır. Aslında, Java'da Kore'ye (projenin uyguladığı dil) benziyor, ancak stil temelde ML ile aynı. Fakat Kore'nin felsefesi, yazarın kodunu biçimlendirmemesi gerektiğidir, bu nedenle Java kodlarından hiçbiri biçimlendirilmemiştir (otomatik olarak biçimlendirilmiştir).
listedeki n öğelerini bırak :
public static <T> List<T> drop(List<T> l, Integer n) {
return n == 0 ? l : drop(l.cons().tail, n - 1);
}
Eğer baş ve kuyruk ayıklamak için desen maçı ediyorum ML / Haskell, olarak, burada diyorsunuz list.cons().x
ve list.cons().tail
.
listeye bir öğe ekle :
public static <T> List<T> insert(List<T> l, Integer i, T x) {
if (i == 0)
return cons(x, l);
return cons(l.cons().x, insert(l.cons().tail, i - 1, x));
}
Liste olduğu belirlenen cebirsel veri türü tanımlanmış olacağını anlamıyla nasıl. Tutulma tarafından üretilen kazan plakasının kaldırıldığı bir versiyon:
public final class List<T> {
public static final class Nil<T> {
}
public static final class Cons<T> {
public final T x;
public final List<T> tail;
public Cons(T x, List<T> tail) {
if (x == null)
throw new RuntimeException("null head");
if (tail == null)
throw new RuntimeException("null tail");
this.x = x;
this.tail = tail;
}
}
private final Nil<T> nil;
private final Cons<T> cons;
private List(Nil<T> nil, Cons<T> cons) {
this.nil = nil;
this.cons = cons;
}
public boolean isEmpty() {
return nil != null;
}
public Nil<T> nil() {
if (nil == null)
throw new RuntimeException("not nil");
return nil;
}
public Cons<T> cons() {
if (cons == null)
throw new RuntimeException("not cons");
return cons;
}
public static <T> List<T> cons(Cons<T> cons) {
if (cons == null)
throw new RuntimeException("constructor received null");
return new List<T>(null, cons);
}
public static <T> List<T> nil(Nil<T> nil) {
if (nil == null)
throw new RuntimeException("constructor received null");
return new List<T>(nil, null);
}
}
İşte bir trie açısından uygulanan bir harita veri yapısı :
public final class Map<K, V> {
private final Tree<Character, Optional<Pair<K, V>>> tree;
// keys are sorted in reverse order so entrySet can use cons instead of append
private final Comparer<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> comparer =
new PairLeftComparer<Character, Tree<Character, Optional<Pair<K, V>>>>(
new ReverseComparer<Character>(new CharacterComparer()));
private Map(Tree<Character, Optional<Pair<K, V>>> tree) {
this.tree = tree;
}
public static <K, V> Map<K, V> empty() {
return new Map<K, V>(new Tree<Character, Optional<Pair<K, V>>>(
OptionalUtils.<Pair<K, V>> nothing(),
ListUtils
.<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> nil()));
}
public Optional<V> get(K k) {
Tree<Character, Optional<Pair<K, V>>> t = tree;
for (char c : k.toString().toCharArray()) {
Tree<Character, Optional<Pair<K, V>>> t2 = getEdge(t, c);
if (t2 == null)
return nothing();
t = t2;
}
if (t.v.isNothing())
return nothing();
return some(t.v.some().x.y);
}
public Map<K, V> put(K k, V v) {
return new Map<K, V>(put(tree, k.toString(), v, k));
}
private Tree<Character, Optional<Pair<K, V>>> put(
Tree<Character, Optional<Pair<K, V>>> t, String s, V v, K k) {
if (s.equals(""))
return new Tree<Character, Optional<Pair<K, V>>>(some(Pair.pair(k, v)),
t.edges);
char c = s.charAt(0);
Tree<Character, Optional<Pair<K, V>>> t2 = getEdge(t, c);
if (t2 == null)
return new Tree<Character, Optional<Pair<K, V>>>(
t.v,
sort(
cons(
pair(
c,
put(new Tree<Character, Optional<Pair<K, V>>>(
OptionalUtils.<Pair<K, V>> nothing(),
ListUtils
.<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> nil()),
s.substring(1), v, k)), t.edges), comparer));
return new Tree<Character, Optional<Pair<K, V>>>(t.v, sort(
replace(pair(c, put(t2, s.substring(1), v, k)), t.edges), comparer));
}
private List<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> replace(
Pair<Character, Tree<Character, Optional<Pair<K, V>>>> edge,
List<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> edges) {
if (edges.cons().x.x.equals(edge.x))
return cons(edge, edges.cons().tail);
return cons(edges.cons().x, replace(edge, edges.cons().tail));
}
// I consider this O(1). There are a constant of 2^16 values of
// char. Either way it's unusual to have a large amount of
// edges since only ASCII chars are typically used.
private Tree<Character, Optional<Pair<K, V>>> getEdge(
Tree<Character, Optional<Pair<K, V>>> t, char c) {
for (Pair<Character, Tree<Character, Optional<Pair<K, V>>>> p : iter(t.edges))
if (p.x.equals(c))
return p.y;
return null;
}
public Map<K, V> delete(K k) {
return new Map<K, V>(delete(tree, k.toString()).x);
}
private Pair<Tree<Character, Optional<Pair<K, V>>>, Boolean> delete(
Tree<Character, Optional<Pair<K, V>>> t, String k) {
if (k.equals(""))
return pair(
new Tree<Character, Optional<Pair<K, V>>>(
OptionalUtils.<Pair<K, V>> nothing(), t.edges), t.edges.isEmpty());
char c = k.charAt(0);
Tree<Character, Optional<Pair<K, V>>> t2 = getEdge(t, c);
if (t2 == null)
return pair(t, false);
Pair<Tree<Character, Optional<Pair<K, V>>>, Boolean> p =
delete(t2, k.substring(1));
List<Pair<Character, Tree<Character, Optional<Pair<K, V>>>>> edges = nil();
for (Pair<Character, Tree<Character, Optional<Pair<K, V>>>> e : iter(t.edges))
if (!e.x.equals(c))
edges = cons(e, edges);
if (!p.y)
return pair(
new Tree<Character, Optional<Pair<K, V>>>(t.v, cons(pair(c, p.x),
edges)), false);
boolean oneEdge = t.edges.cons().tail.isEmpty();
return pair(new Tree<Character, Optional<Pair<K, V>>>(t.v, edges), oneEdge
&& t.v.isNothing());
}
public static class Entry<K, V> {
public Entry(K k, V v) {
this.k = k;
this.v = v;
}
public final K k;
public final V v;
}
public List<Entry<K, V>> entrySet() {
return entrySet(ListUtils.<Entry<K, V>> nil(), tree);
}
private List<Entry<K, V>> entrySet(List<Entry<K, V>> l,
Tree<Character, Optional<Pair<K, V>>> t) {
if (!t.v.isNothing()) {
Pair<K, V> p = t.v.some().x;
l = cons(new Entry<K, V>(p.x, p.y), l);
}
for (Pair<Character, Tree<Character, Optional<Pair<K, V>>>> e : iter(t.edges))
l = entrySet(l, e.y);
return l;
}
}
Türler kod kadar alan kaplar. Örneğin, koymak , yöntem türlerinden 302 karakter ve kod 343 karakter (boşluk / yeni satır hariç) sahiptir.
.litcoffee
. O yardımcı olabilir.