2012-01-06 81 views
3

雖然我認爲自己是一箇中間值較低的Haskeller(理解RankNTypes,但是與箭頭「proc」符號糾纏在一起),但我對Java並不看好。儘管如此,我決定在Java中我無法做的一件事情與Ix類型類和Haskell的靈活索引數組類似。我着手製作我自己的作品,但是我對我自己的經驗不足表示贊同。任何人都可以給我任何建議或指針在這項任務?我是否全力以赴,還是有正確的想法? Java SE 7 Platform是否已經有了這樣的東西,我不知何故錯過了?有其他人已經完成了嗎?將可擴展數組索引(Ix和族)移植到Java

我有以下接口模擬Ix型類:

public interface Ix<T extends Ix<T>> { 
    int indexIn(IxRange<T> range); 
    boolean isIn(IxRange<T> range); 
    boolean isFirstIn(IxRange<T> range); 
    boolean isLastIn(IxRange<T> range); 
    T nextIndexIn(IxRange<T> range); 
    T prevIndexIn(IxRange<T> range); 
    IxRange<T> maxRange(); 
} 

我不能原生類型類複製正是由於缺乏對接口的靜態方法,像往常一樣與Java,但我認爲這是一個合理的方式(除了maxRange(),這只是錯誤的)。如果有人有更好的想法,請告訴我。因爲我沒有可用的元組(我不想依賴於FunctionalJava),所以我提出了以下類(Ix<T>方法,其中,省略)。

public class IxRange<T extends Ix<T>> implements Ix<IxRange<T>> { 
    public final T lowerBound; 
    public final T upperBound; 

    public IxRange(T lB,T uB) { 
     lowerBound = lB; 
     upperBound = uB; 
    } 

    public int rangeSize() { 
     return upperBound.indexIn(this) - lowerBound.indexIn(this); 
    } 
} 

我再有這樣開始的一類:

public class FlexArray<I extends Ix<I>,E> extends AbstractList<E> implements Cloneable 

這是我遇到的最麻煩的,主要的,但絕不排,由於第一需要的情況下,爲了致電maxRange()(gah!)。我也有幾個包裝類,用於實現接口Ix<T>的常見類型,但這是一個輔助問題。總之,我正在尋找如何繼續的建議,並且如果可能的話,如何重構Ix<I>以擺脫maxRange()並將其替換爲更好的東西。這項任務的一般想法也受到歡迎,但這不是這個問題的要點。

+1

不知道這是否有幫助,但弗雷格(code.google。com/p/frege)可以將源自Haskell98/2010的源代碼轉換爲Java。生成的代碼仍然取決於Frege Runtime,但也許會提供一個想法如何去做。 OTOH,如果你不想懶惰,那不會有太大的幫助。 – Ingo 2012-01-06 11:01:27

回答

4

我的方法是使用「first class typeclasses」,也稱爲「概念模式」,您不會得出推論,它不像使用oo接口那樣乾淨,但在需要時更有意義比如二進制方法。您可以完全避免簡化事物的「好奇經常性的通用模式」(Ix<T extends Ix<T>>),但在需要的費用由專人傳遞的字典

public interface Ix<A>{ 
    public List<A> range(A start,A end); 
    public int index(A start,A end,A el); 
    public boolean inRange(A start,A end,A el); 
    public int rangeSize(A start,A end); 
} 

要使用此功能,您只需創建你的「實例」喜歡你會在Haskell

public class IxInteger extends Ix<Integer>{ 
    //use the singelton pattern 
    private static IxInteger instance = new IxInteger(); 
    public static IxInteger getInstance(){ 
     return instance; 
    } 
    private IxInteger(){ 
     //most likely doesn't need to do anything 
    } 
    //implement the typeclass 
    public List<Integer> range(Integer start,Integer end){ 
     List<Integer> list = new ArrayList<Integer>(end-start); 
     for(int i = start; i < end; i++){ 
      list.add(i); 
     } 
     return list; 
    } 
    ... 
} 

然後你只要在你需要的時候傳遞字典。

public Foo ixFoo<A>(args..,Ix<A> ixDict){ 
    // do stuff 
    ... 
    // and when you need the dictionary 
    myList = ixDict.range(start,end); 
    ... 
} 

編輯:一個問題是,翻譯代碼時,有時你做愚蠢的事情。在Haskell [a]被用作可迭代集合的一種通用接口。這在嚴格的語言中不起作用。所以,我們可能應該用迭代器代替我的代碼中的List<A>。在這樣的時代最好保持懶惰。

+0

然後,你可以像踐踏你一樣踐踏「列表」方法中的一個或兩個,那麼可以嗎?我總是被告知這是一個禁忌。 :/ – 2012-01-06 01:39:54

+1

我不會擔心它,因爲你不可能有任何可能是'List'和'Ix'實例的東西 – 2012-01-06 03:03:16