你應該只使用兩個構造兩個可能的形狀:
data Option = NoA String | WithA String Int
當然,你應該給他們更好的名字,根據他們代表什麼。幻像類型在這裏肯定是矯枉過正,我建議避免Either
- Left
和Right
不是很自我記錄的構造函數名稱。
如果是有意義的解釋B場的兩者或者分支機構表示相同的數據,那麼你應該定義一個反映這種解釋的功能:
b :: Option -> MeaningOfB
b (NoA s) = ...
b (WithA t n) = ...
如果您有保持不變沒有字段無論選擇什麼,你都應該用它們全部創建一個新的數據類型,並將它包含在兩個構造函數中。如果您爲每個構造函數創建一條記錄,則可以在每個構造函數中爲公共字段指定相同的名稱,以便您可以從任何Option
值中提取該值,而無需在其上進行模式匹配。
基本上,想想它意味着字符串不存在:它改變了關於其他領域,什麼保持不變?無論相應的施工人員有何變化,不管保持不變,都應該分解成它自己的類型。 (這是一個很好的設計原則!)
如果你來自OOP背景,你可以用構圖而不是繼承的方式來思考這個問題 - 但是儘量不要把這個比喻說得太過分。
我不認爲Haskell 2010有什麼可以讓你在以前的解決方案。我會建議去'Either String(String,Int)',或者一個同構類型,比如'data Option = OptionA String | OptionB String Int',其中構造函數具有明智的名稱。 – 2011-12-24 17:15:48
爲了最好地回答這個問題,知道附加在a和b上的*意思很重要。爲什麼有時候你沒有'a'(例如它是'Nothing')?爲什麼可以將'b'表示爲'String' *或* Int'?你爲什麼要強制執行你所談論的限制?這給了我最初的印象:「b」沒有很好的定義。 – 2011-12-24 20:08:06