我已经定义了以下记录:
data Option = Option {
a :: Maybe String,
b :: Either String Int
} deriving (Show)
Run Code Online (Sandbox Code Playgroud)
反正我是否强制执行a Nothing,b必须是a Left,当a是Just,b必须是a Right?也许用幻影类型或其他东西?或者我必须将整个东西包裹在一个Either中并制作它Either String (String, Int)吗?
ehi*_*ird 18
您应该为两种可能的形状使用两个构造函数:
data Option = NoA String | WithA String Int
Run Code Online (Sandbox Code Playgroud)
当然,你应该根据它们所代表的内容给它们更好的名字.幻影类型在这里肯定是矫枉过正,我建议避免Either- Left并且Right不是非常自我记录的构造函数名称.
如果将b字段的两个分支都解释为表示相同的数据是有意义的,那么您应该定义一个反映这种解释的函数:
b :: Option -> MeaningOfB
b (NoA s) = ...
b (WithA t n) = ...
Run Code Online (Sandbox Code Playgroud)
如果您的字段保持不变,无论选择什么,您应该创建一个包含所有这些字段的新数据类型,并将其包含在两个构造函数中.如果你把每个构造一个记录,你可以给公共字段相同的名字在每一个构造函数,这样就可以从任何提取它Option的值,而不必模式匹配就可以了.
基本上,想想字符串不存在意味着什么:它对其他字段有什么改变,什么保持不变?各个构造函数应该发生什么变化; 无论什么样的停留都应该考虑到它自己的类型.(这一般是一个很好的设计原则!)
如果你来自OOP背景,你可以在构思而不是继承的推理方面考虑这一点 - 但是尽量不要把这个类比推得太远.