1

所以我有一个这样的结构:

data Maybe a = Nothing | Just a  

但我想要一个定义为的结构

data MaybeInt = Nothing | Just Int

有没有办法定义MaybeIntusing Maybe a,如果是这样,如何定义?

4

1 回答 1

10

有几种方法可以定义MaybeInt. 我会陈述他们然后有一些评论。

直接的

data MaybeInt = NothingInt | JustInt Int

新型

newtype MaybeInt = MI (Maybe Int)

类型同义词

type MaybeInt = Maybe Int

清楚的

-- just use `(Maybe Int)` wherever you would write `MaybeInt`

评论

最常见的是,人们会使用简单的方法,因为大多数人都熟悉Maybe并知道如何使用JustNothing匹配它。这使它对图书馆有好处——非常透明。类型同义词方法是一种常见的文档方法,但对于您的同义词基本上没用。它使得它foo :: Int -> Maybe Int具有bar :: Int -> MaybeInt相同的类型签名。这也意味着一旦有人知道MaybeInt === Maybe Int他们可以使用Just/Nothing构造函数进行匹配。

newtype方法变得相当有趣。每次要使用type时,您都必须在此处开始“包装”和“展开”MI 构造函数。比较:MaybeInt

baz :: MaybeInt -> Bool
baz (MI Nothing) = False
baz (MI (Just int)) = True

这很好,因为如果您不导出 MI,那么没有人将能够匹配MaybeInt(尽管对其中发生的事情有很好的猜测)。这对于制作稳定的 API 非常有用。的另一个有趣的属性newtype是你可以编写不同于's 内置的newinstance的 s 。例如,您可以覆盖实例MaybeIntMaybeMonoid

instance Monoid MaybeInt where
  mempty = MI Nothing
  mi `mappend` (MI Nothing) = mi
  _  `mappend` mi           = mi

这与包含s 的Last a内置 newtype相同。Data.MonoidMaybe a

最后,我们得到了完整的data实例。它更冗长、更容易出错、速度稍慢(因为编译器必须跟踪新的、唯一的数据类型),并且需要人们学习新的构造函数。对于如此明显相同Maybe Int的功能,根本没有理由使用它。

于 2013-02-13T16:07:51.170 回答