Haskell中数据类型的别名

Dan*_*ath 1 haskell types

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

data Maybe a = Nothing | Just a  
Run Code Online (Sandbox Code Playgroud)

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

data MaybeInt = Nothing | Just Int
Run Code Online (Sandbox Code Playgroud)

有没有办法定义MaybeInt使用Maybe a,如果有,如何?

J. *_*son 9

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

直接

data MaybeInt = NothingInt | JustInt Int
Run Code Online (Sandbox Code Playgroud)

NEWTYPE

newtype MaybeInt = MI (Maybe Int)
Run Code Online (Sandbox Code Playgroud)

输入同义词

type MaybeInt = Maybe Int
Run Code Online (Sandbox Code Playgroud)

-- just use `(Maybe Int)` wherever you would write `MaybeInt`
Run Code Online (Sandbox Code Playgroud)

评论

最常见的是,人们会使用普通方法,因为大多数人都熟悉Maybe并因此知道使用JustNothing匹配它.这使它对图书馆有益 - 非常透明.该类型的同义词的方法是一种常用的文档的方法,但基本上是无用的代名词.这使得它,以便foo :: Int -> Maybe Intbar :: Int -> MaybeInt具有相同类型的签名.这也意味着只要有人知道MaybeInt === Maybe Int他们可以使用Just/ Nothingconstructors进行匹配.

NEWTYPE方法变得相当有趣.在这里,每次要使用该类型时,都必须开始"包装"和"展开" MI 构造函数.相比:MaybeInt

baz :: MaybeInt -> Bool
baz (MI Nothing) = False
baz (MI (Just int)) = True
Run Code Online (Sandbox Code Playgroud)

这很好,因为如果你不导出 MI那么没有人能够匹配MaybeInt(尽管有一个很好的猜测内部发生了什么).这对于制作稳定的API非常有用.另一个有趣的特性newtype是你可以编写与s内置的不同的新instances .例如,您可以覆盖实例MaybeIntMaybeMonoid

instance Monoid MaybeInt where
  mempty = MI Nothing
  mi `mappend` (MI Nothing) = mi
  _  `mappend` mi           = mi
Run Code Online (Sandbox Code Playgroud)

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

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