简体   繁体   English

Haskell中数据类型的别名

[英]Alias for datatypes in Haskell

So I've got a structure like this: 所以我有一个这样的结构:

data Maybe a = Nothing | Just a  

but I want a structure that is defined as 但我想要一个定义为的结构

data MaybeInt = Nothing | Just Int

is there a way to define MaybeInt using Maybe a , and if so how? 有没有一种方法可以使用Maybe a定义MaybeInt

There are a few ways to define MaybeInt . 有几种方法可以定义MaybeInt I'll state them then have some commentary. 我先说一下,然后再做些评论。

Direct 直接

data MaybeInt = NothingInt | JustInt Int

Newtype 新类型

newtype MaybeInt = MI (Maybe Int)

Type synonym 类型同义词

type MaybeInt = Maybe Int

Plain 平原

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

Commentary 评论

Most commonly, one would use the plain method since most people are familiar with Maybe and thus know to use Just and Nothing to match it. 最常见的是,因为大多数人都熟悉Maybe ,因此知道使用Just and Nothing来匹配它,所以将使用简单方法。 This makes it good for libraries—very transparent. 这非常适合库-非常透明。 The type synonym method is a common documentation method, but is basically useless for your synonym. 类型同义词方法是一种常见的文档编制方法,但是对于您的同义词基本上是没有用的。 It makes it so that foo :: Int -> Maybe Int and bar :: Int -> MaybeInt have identical type signatures. 它使得foo :: Int -> Maybe Int bar :: Int -> MaybeInt foo :: Int -> Maybe Intbar :: Int -> MaybeInt具有相同的类型签名。 It also means that as soon as someone knows that MaybeInt === Maybe Int they can use the Just / Nothing constructors for matching. 这也意味着,只要有人知道MaybeInt === Maybe Int他们就可以使用Just / Nothing构造函数进行匹配。

The newtype method gets fairly interesting. newtype方法变得相当有趣。 Here you have to begin "wrapping" and "unwrapping" the MI constructor every time you want to use the MaybeInt type . 在这里,每次要使用MaybeInt 类型时,都必须开始“包装”和“展开” MI 构造函数 Compare: 相比:

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

this is nice because if you don't export MI then nobody will be able to match on MaybeInt (despite having a pretty good guess at what's going on inside of it). 这很好,因为如果您不导出 MI那么没人会在MaybeInt上进行匹配(尽管可以很好地猜测其中发生了什么)。 This is really useful for making stable APIs. 这对于制作稳定的API确实很有用。 Another interesting property of newtype is that you can write new instance s for MaybeInt which are different from Maybe 's built-in ones. 另一个有趣的特性newtype是,你可以写新的instance对于s MaybeInt这是从不同的Maybe的内置的。 For instance, you could override the Monoid instance 例如,您可以覆盖Monoid实例

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

which is just the same as the Last a newtype built-in to Data.Monoid which wraps Maybe a s. 这与Data.Monoid内置的Last a Data.Monoid ,后者包装Maybe a

Finally, we get the full-blown data instance. 最后,我们获得了完整的data实例。 It's more verbose, more likely to error, marginally slower (since the compiler has to track a new, unique data type), and requires that people learn new constructors. 它更冗长,更容易出错,速度稍慢(因为编译器必须跟踪新的唯一数据类型),并且要求人们学习新的构造函数。 For functionality so obviously identical to Maybe Int there's really no reason to use it at all. 对于与Maybe Int如此明显相同的功能,实际上根本没有理由使用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM