package ktak.immutablejava;

public abstract class Option<T> {
    
    public abstract <R> R visit(Visitor<R,T> visitor);
    
    public abstract <U> Option<U> mapSome(Function<T,U> f);
    
    public interface Visitor<R,T> {
        public R visitNone();
        public R visitSome(T value);
    }
    
    public static final class None<T> extends Option<T> {
        
        @Override
        public <R> R visit(Visitor<R, T> visitor) {
            return visitor.visitNone();
        }
        
        @Override
        public <U> Option<U> mapSome(Function<T, U> f) {
            return none();
        }
        
    }
    
    public static final class Some<T> extends Option<T> {
        
        private final T val;
        
        public Some(T val) {
            this.val = val;
        }
        
        @Override
        public <R> R visit(Visitor<R, T> visitor) {
            return visitor.visitSome(val);
        }
        
        @Override
        public <U> Option<U> mapSome(Function<T, U> f) {
            return some(f.apply(val));
        }
        
    }
    
    public static <T> Option<T> none() { return new None<T>(); }
    
    public static <T> Option<T> some(T val) { return new Some<T>(val); }
    
}

@@ -113,32 +113,146 @@
  visitor);%0A    %0A
+    public abstract %3CR%3E R match(%0A            Function%3CUnit,R%3E noneCase,%0A            Function%3CT,R%3E someCase);%0A    %0A
     public abstr
@@ -295,16 +295,16 @@
 ,U%3E f);%0A
-
     %0A   
@@ -723,32 +723,230 @@
      %7D%0A        %0A
+        @Override%0A        public %3CR%3E R match(%0A                Function%3CUnit, R%3E noneCase,%0A                Function%3CT, R%3E someCase) %7B%0A            return noneCase.apply(Unit.unit);%0A        %7D%0A        %0A
     %7D%0A    %0A    p
@@ -1320,32 +1320,32 @@
 tion%3CT, U%3E f) %7B%0A
-
             retu
@@ -1378,32 +1378,224 @@
      %7D%0A        %0A
+        @Override%0A        public %3CR%3E R match(%0A                Function%3CUnit, R%3E noneCase,%0A                Function%3CT, R%3E someCase) %7B%0A            return someCase.apply(val);%0A        %7D%0A        %0A
     %7D%0A    %0A    p

add match method to Option