你应该只使用两个构造两个可能的形状:
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