[英]Derive monoid instance for custom `Maybe` data type
出于学习目的,我试图在Monoid
的typeclass实例中创建一个模拟Maybe
的Optional
数据类型,其中
-- Data.Monoid> Prelude.mappend (Just [1,2]) (Just [3,4])
-- Just [1,2,3,4]
相反,我得到了Maybe
for Monoid
的First
实例的行为。
-- 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
外观。 Sum
和Product
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.