所以我有一个像这样的结构:
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,如果有,如何?
有几种方法可以定义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并因此知道使用Just和Nothing匹配它.这使它对图书馆有益 - 非常透明.该类型的同义词的方法是一种常用的文档的方法,但基本上是无用的代名词.这使得它,以便foo :: Int -> Maybe Int与bar :: 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根本没有理由使用它.