[英]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.