For learning purposes, i am trying to create an Optional
data type that mimics Maybe
in the typeclass instance of Monoid
where
-- 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
.
-- Data.Monoid> (First (Just [1,2])) <> (First (Just [3,4]))
-- First {getFirst = Just [1,2]}
My data type and typeclass instance are:
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
mappend
for Optional
to behave like the instance for Maybe
that concatenates lists rather than taking the first Only
value? Why does it behave like this?
Because that is how First
has been designed. The idea of First
is to "wrap" a Maybe a
value, and to implement the Monoid
like:
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. This can be useful when we use the 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. A similar thing happens with Sum
and Product
How do I get
mappend
forOptional
to behave like the instance forMaybe
that concatenates lists rather than taking the firstOnly
value?
There is an error in your definition. You use mempty
in the head of a function like:
mappend x = x
is just a variable named 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 = x
mappend x = x
mappend (Only x) (Only y) = Only (Prelude.mappend x y)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.