所以我有这样的结构:
data Maybe a = Nothing | Just a
但我想要一个定义为
的结构data MaybeInt = Nothing | Just Int
有没有办法使用MaybeInt
来定义Maybe a
,如果有,怎么办?
答案 0 :(得分:9)
有几种方法可以定义MaybeInt
。我会说他们然后有一些评论。
直接
data MaybeInt = NothingInt | JustInt Int
NEWTYPE
newtype MaybeInt = MI (Maybe Int)
输入同义词
type MaybeInt = Maybe Int
纯
-- just use `(Maybe Int)` wherever you would write `MaybeInt`
<强>评论强>
最常见的是,人们会使用普通方法,因为大多数人都熟悉Maybe
,因此知道使用Just
和Nothing
来匹配它。这使它对图书馆有益 - 非常透明。 类型同义词方法是一种常见的文档方法,但对于您的同义词基本上没用。它使foo :: Int -> Maybe Int
和bar :: Int -> MaybeInt
具有相同的类型签名。这也意味着只要有人知道MaybeInt === Maybe Int
他们就可以使用Just
/ Nothing
构造函数进行匹配。
newtype 方法非常有趣。每次要使用MI
类型时,您必须开始“包装”和“展开”MaybeInt
构造函数。比较:
baz :: MaybeInt -> Bool
baz (MI Nothing) = False
baz (MI (Just int)) = True
这很好,因为如果你没有导出 MI
那么就没有人可以在MaybeInt
上匹配(尽管对内部发生的事情有很好的猜测)它)。这对于制作稳定的API非常有用。 newtype
的另一个有趣属性是,您可以为instance
编写与MaybeInt
内置的Maybe
不同的新Monoid
。例如,您可以覆盖instance Monoid MaybeInt where
mempty = MI Nothing
mi `mappend` (MI Nothing) = mi
_ `mappend` mi = mi
实例
Last a
与包含Data.Monoid
的{{1}}内置的Maybe a
新类型相同。
最后,我们得到了成熟的data
实例。它更冗长,更容易出错,速度稍慢(因为编译器必须跟踪新的,唯一的数据类型),并要求人们学习新的构造函数。对于明显与Maybe Int
完全相同的功能,根本没有理由使用它。