出于学习目的,我试图在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)
值?答案 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
的外观。 Sum
和Product
如何让
mappend
的{{1}}像Optional
的实例那样串联列表,而不是采用第一个Maybe
值?
您的定义中有一个错误。您可以在函数的开头使用Only
,例如:
mempty
只是一个名为mappend x mempty = x
的变量。因此,第一行将匹配一切。您应该修复它,就像您打算的那样:
mempty