Java 開發者的函數式程式設計(2)代數資料型態
Java 開發者的函數式程式設計(1)初探函數式程式設計 << 前情 我們大多熟悉物件導向程式設計,熟悉抽象資料型態(Abstract data type, ADT)。抽象資料型態的模型中封裝了資料結構與實作,僅透露互動時的公開介面;然而,代數資料型態(Algebraic data type)相對地曝露了基本的資料結構及規律性,在函數式程式設計的領域中,代數資料型態是基本元素。 (ADT 廣泛應用為 Abstract Data Type 的縮寫,在函數式程式設計中並不使用這個縮寫,因此英文中都直接使用 Abstract Data Type 作為全名。) Java 是物件導向程式語言,對代數資料型態沒有直接的支援,有兩種方式可以模擬該型態。由於代數資料型態會曝露基本的資料結構,因而可使用具公開值域(Field)的類別來模擬代數資料型態,不過,許多物件導向原則並不鼓勵公開值域,如此一來就得尋找其他方式來模擬。因為代數資料型態會曝露規律性,規律性這聽起來像個行為表現,在 Java 中討論行為時,通常會使用 以清單類型為例,我們知道 Java SE API 中定義了 public interface List<T> { T head(); List<T> tail(); } 這種清單的實例之一是空清單,若運用以上介面來實作一個空清單的話,可以如下… public class AlgebraicType { private static List<? extends Object> Nil = new List<Object>() { public Object head() { return null; } public List<Object> tail() { return null; } public String toString() { return "[]"; } }; @SuppressWarnings("unchecked") public static <T> List<T> nil() { return (List<T>) Nil; } } 也就是說,空清單沒頭沒尾。為了方便,我們也定義了一個 如果有個清單 為了方便,我們來定義一個 public class AlgebraicType { ... public static <T> List<T> cons(final T x, final List<T> xs) { return new List<T>() { private T head; private List<T> tail; { this.head = x; this.tail = xs; } public T head(){ return this.head; } public List<T> tail() { return this.tail; } public String toString() { return head() + ":" + tail(); } }; } } 一旦有了 cons(1, nil()); // 1:[] 具有元素 2、1 的清單,則可以使用以下程式碼來建立: cons(2, cons(1, nil())); // 2:1:[] 具有元素 3、2、1 的清單,則可以使用以下程式碼來建立: cons(3, cons(2, cons(1, nil()))); // 3:2:1:[] 為了方便,可以定義一個 public class AlgebraicType { … @SafeVarargs public static <T> List<T> list(T... elems) { if(elems.length == 0) return nil(); T[] remain = Arrays.copyOfRange(elems, 1, elems.length); return cons(elems[0], list(remain)); } } 如此要建立具元素 1、2、3、4 的清單就可以如下: list(1, 2, 3, 4); // 1:2:3:4:[] 這邊定義的 那麼,為什麼代數資料型態適用於分而治之(Divide-and-conquer)的場合?以這邊的 一個子問題是,呼叫 這就又有一個問題了,怎麼用剩餘引數作為尾清單?可以遞迴地用剩餘引數來呼叫 |
Jeff Chen
08/13
良葛格 您好
晚輩最近恰巧接觸 functional programming
加上過去慣用的語言剛好是 Java (學習的過程中常受益於您的筆記)
手邊遇上了將現有 haskell 程式以 Java 重新編寫的工作
其中 algebraic data type 的部分因個人興趣有作稍微的功課
當然不同的 algebraic data type 所適合的 Java 詮釋各有不同
在網路上搜尋到的相關文章中常見以 abstract class 為模版再以不同的 subclass 實現 constructors
而在 haskell code 中常見到的 algebraic data type 大多作為
”sum of a set of constructors“
想請教如果面對這樣的需求 在 Java 的思考邏輯上應該採取何種實現?