自定义`Maybe`数据类型的派生Monoid实例

时间:2018-10-20 13:14:52

标签: haskell

出于学习目的,我试图在Optional的typeclass实例中创建一个模仿Maybe的{​​{1}}数据类型,

Monoid

相反,我得到了-- Data.Monoid> Prelude.mappend (Just [1,2]) (Just [3,4]) -- Just [1,2,3,4] 的{​​{1}}的{​​{1}}实例的行为。

First

我的数据类型和typeclass实例是:

Maybe

我的问题是

  • 为什么会这样?
  • 如何让Monoid的{​​{1}}像-- Data.Monoid> (First (Just [1,2])) <> (First (Just [3,4])) -- First {getFirst = Just [1,2]} 的实例那样串联列表,而不是采用第一个data Optional a = Nada | Only a deriving (Eq, Show) instance Monoid a => Monoid (Optional a) where mempty = Nada mappend x mempty = x mappend mempty (Only x) = Only x mappend (Only x) (Only y) = Only (Prelude.mappend x y) 值?

1 个答案:

答案 0 :(得分:2)

  

为什么会这样?

因为这就是First的设计方式。 First的想法是“包装” Maybe a值,并像下面这样实现Monoid

instance Monoid (First a) where
    mempty = First Nothing
    mappend l@(First (Just _)) _ = l
    mappend _ x = x

因此,它返回第一个First构造函数,该构造函数包装了值Just数据构造函数。当我们使用mconcat时,这会很有用:

Prelude Data.Monoid> mconcat [First Nothing, First (Just 0), First Nothing, First (Just 118), First (Just 999)]
First {getFirst = Just 0}

因此,我们不使用Monoid (Maybe a)实现,First决定Monoid的外观。 SumProduct

也会发生类似的情况
  

如何让mappend的{​​{1}}像Optional的实例那样串联列表,而不是采用第一个Maybe值?

您的定义中有一个错误。您可以在函数的开头使用Only,例如:

mempty

只是一个名为mappend x mempty = x 的变量。因此,第一行将匹配一切。您应该修复它,就像您打算的那样:

mempty