interface StringList {
  public StringList add(String s);
  int length();
  boolean contains(String s);
}
class SLLink implements StringList {
  String value; StringList rest;
  public SLLink(String value, StringList rest) {
    this.value = value; this.rest = rest;
  }
  public StringList add(String s) { return new SLLink(s, this); }
  public int length() { return 1 + this.rest.length(); }
  public boolean contains(String s) {
    return this.value.equals(s) || this.rest.contains(s);
  }
}
class SLEmpty implements StringList {
  public StringList add(String s) { return new SLLink(s, this); }
  public int length() { return 0; }
  public boolean contains(String s) { return false; }
}


interface IntegerList {
  IntegerList add(Integer s);
  int length();
  boolean contains(Integer s);
}
class ILLink implements IntegerList {
  Integer value;
  IntegerList rest;
  public ILLink(Integer value, IntegerList rest) {
    this.value = value; this.rest = rest;
  }
  public IntegerList add(Integer s) { return new ILLink(s, this); }
  public int length() { return 1 + this.rest.length(); }
  public boolean contains(Integer s) {
    return this.value.equals(s) || this.rest.contains(s);
  }
}
class ILEmpty implements IntegerList {
  public IntegerList add(Integer s) { return new ILLink(s, this); }
  public int length() { return 0; }
  public boolean contains(Integer s) { return false; }
}


interface List<T> {
  List<T> add(T t);
  int length();
  boolean contains(T s);
}
class Link<T> implements List<T> {
  T value;
  List<T> rest;
  public Link(T value, List<T> rest) {
    this.value = value;
    this.rest = rest;
  }
  public Link<T> add(T s) {
    return new Link<T>(s, this);
  }
  public int length() {
    return 1 + this.rest.length();
  }
  public boolean contains(T s) {
    return this.value.equals(s) || this.rest.contains(s);
  }
  public String toString() {
    return "Link(" + this.value.toString() + ", " + this.rest.toString() + ")";
  }
}
class Empty<T> implements List<T> {
  public Link<T> add(T s) {
    return new Link<T>(s, this);
  }
  public int length() {
    return 0;
  }
  public boolean contains(T s) {
    return false;
  }
  public String toString() {
    return "Empty";
  }
}




public class GLinks {
  public static void main(String args[]) {
    Link<Integer> dlist = new Empty<Integer>().add(12).add(13);
    System.out.println(dlist + " contains 12? " + dlist.contains(12));

    Link<String> slist = new Empty<String>().add("a").add("b");
    System.out.println(slist + " contains b? " + slist.contains("b"));

    List<Integer> dlist2 = new Link<Integer>(5, dlist);
    System.out.println(dlist2);

    List<Object> olist = new Link<Object>("a", new Link<Object>(5, new Empty<Object>()));
    System.out.println(olist);

  }
}


