简体   繁体   English

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

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

For learning purposes, i am trying to create an Optional data type that mimics Maybe in the typeclass instance of Monoid where 出于学习目的,我试图在Monoid的typeclass实例中创建一个模拟MaybeOptional数据类型,其中

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

Instead, I am getting the behavior of the First instance of Maybe for Monoid . 相反,我得到了Maybe for MonoidFirst实例的行为。

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

My data type and typeclass instance are: 我的数据类型和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)

My questions are 我的问题是

  • Why does it behave like this? 为什么会这样呢?
  • How do I get mappend for Optional to behave like the instance for Maybe that concatenates lists rather than taking the first Only value? 如何获得mappend用于Optional的行为像实例Maybe是符连接列表而不是将第一Only值?

Why does it behave like this? 为什么会这样呢?

Because that is how First has been designed. 因为这就是First设计方式。 The idea of First is to "wrap" a Maybe a value, and to implement the Monoid like: First的想法是“包装”一个Maybe a值,并像下面这样实现Monoid

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

It thus returns the first First constructor that wrapps a value Just data constructor. 因此,它返回包装了值Just数据构造函数的第一个First构造函数。 This can be useful when we use the mconcat : 当我们使用mconcat时,这可能会很有用:

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

We thus do not use the Monoid (Maybe a) implementation, the First decides how the Monoid looks like. 因此,我们不使用Monoid (Maybe a)实现,由First决定Monoid外观。 A similar thing happens with Sum and Product SumProduct Sum发生类似的情况

How do I get mappend for Optional to behave like the instance for Maybe that concatenates lists rather than taking the first Only value? 如何获得mappend用于Optional的行为像实例Maybe是符连接列表而不是将第一Only值?

There is an error in your definition. 您的定义中有错误 You use mempty in the head of a function like: 您可以在以下函数的开头使用mempty

mappend x mempty = x

is just a variable named mempty . 只是一个名为mempty的变量 So the first line will match everything . 因此,第一行将匹配所有内容 You should fix it, like you intend with: 您应该修复它,就像您打算使用的那样:

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