繁体   English   中英

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

[英]Derive monoid instance for custom `Maybe` data type

出于学习目的,我试图在Monoid的typeclass实例中创建一个模拟MaybeOptional数据类型,其中

-- Data.Monoid> Prelude.mappend (Just [1,2]) (Just [3,4])
-- Just [1,2,3,4]

相反,我得到了Maybe for MonoidFirst实例的行为。

-- Data.Monoid> (First (Just [1,2])) <> (First (Just [3,4]))
-- First {getFirst = Just [1,2]}

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

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)

我的问题是

  • 为什么会这样呢?
  • 如何获得mappend用于Optional的行为像实例Maybe是符连接列表而不是将第一Only值?

为什么会这样呢?

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

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

因此,它返回包装了值Just数据构造函数的第一个First构造函数。 当我们使用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 Sum发生类似的情况

如何获得mappend用于Optional的行为像实例Maybe是符连接列表而不是将第一Only值?

您的定义中有错误 您可以在以下函数的开头使用mempty

mappend x mempty = x

只是一个名为mempty的变量 因此,第一行将匹配所有内容 您应该修复它,就像您打算使用的那样:

instance Monoid a => Monoid (Optional a) where
    mempty = Nada
    mappend x Nada = x
    mappend Nada x = x
    mappend (Only x) (Only y) = Only (Prelude.mappend x y)

暂无
暂无

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

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