use*_*931 5 haskell typeclass monoids
假设我有一个类型
data Options = Options
{ _optionOne :: Maybe Integer
, _optionTwo :: Maybe Integer
, _optionThree :: Maybe String
} deriving Show
Run Code Online (Sandbox Code Playgroud)
有更多的领域。我想Monoid为这种类型定义一个实例,其mempty值是 an Optionswith all fields Nothing。有没有比这更简洁的写法
instance Monoid Options where
mempty = Options Nothing Nothing Nothing
mappend = undefined
Run Code Online (Sandbox Code Playgroud)
Nothing当我Options有更多字段时,这将避免需要写一堆s ?
我建议只写Nothings,甚至明确拼出所有记录字段,这样您就可以确保在添加具有不同mempty值的新字段或重新排序字段时不会错过任何情况:
mempty = Options
{ _optionOne = Nothing
, _optionTwo = Nothing
, _optionThree = Nothing
}
Run Code Online (Sandbox Code Playgroud)
我以前没有尝试过,但似乎您可以为此目的使用泛型派生包,只要您记录的所有字段都是Monoids。您将添加以下语言编译指示和导入:
{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)
import Generics.Deriving.Monoid
Run Code Online (Sandbox Code Playgroud)
添加deriving (Generic)到您的数据类型并将所有非Monoid字段包装在一个类型中,Data.Monoid使用您想要的组合行为,例如First, Last, Sum, 或Product:
data Options = Options
{ _optionOne :: Last Integer
, _optionTwo :: Last Integer
, _optionThree :: Maybe String
} deriving (Generic, Show)
Run Code Online (Sandbox Code Playgroud)
例子:
Last (Just 2) <> Last (Just 3) = Last {getLast = Just 3}First (Just 2) <> First (Just 3) = First {getFirst = Just 2}Sum 2 <> Sum 3 = Sum {getSum = 5}Product 2 <> Product 3 = Product {getProduct = 6}然后使用以下函数 fromGenerics.Deriving.Monoid来创建您的默认实例:
memptydefault :: (Generic a, Monoid' (Rep a)) => a
mappenddefault :: (Generic a, Monoid' (Rep a)) => a -> a -> a
Run Code Online (Sandbox Code Playgroud)
在上下文中:
instance Monoid Options where
mempty = memptydefault
mappend = ...
Run Code Online (Sandbox Code Playgroud)