使用 GHC Generics 定义类似 "mempty" 的函数?
Defining an "mempty"-like function with GHC Generics?
我正在为 Zoho REST API 编写一个客户端库,并且有一堆不同的记录类型,它们具有所有 Maybe a
个字段,即:
data Approval = Approval
{ apDelegate :: Maybe Bool
, apApprove :: Maybe Bool
, apReject :: Maybe Bool
, apResubmit :: Maybe Bool
} deriving (Eq, Show, Generic)
data ContactSpecialFields = ContactSpecialFields
{ csfCurrencySymbol :: Maybe Text -- $currency_symbol
, csfState :: Maybe Text -- $state
, csfProcessFlow :: Maybe Bool -- $process_flow
, csfApproved :: Maybe Bool -- $approved
, csfApproval :: Approval -- $approval
, csfEditable :: Maybe Bool -- $editable
} deriving (Eq, Show)
-- and so on
我需要一种方法来定义 "empty" 这种类型的记录,例如:
emptyApproval :: Approval
emptyApproval = Approval
{ apDelegate = Nothing
, apApprove = Nothing
, apReject = Nothing
, apResubmit = Nothing
}
因此,我联系了 GHC.Generics
并得到了一些有用的东西(这是错误的!):
-- These parts seem logically correct to me...
class GEmptyZohoStructure f where
gEmptyZohoStructure :: f p
instance (GEmptyZohoStructure f, GEmptyZohoStructure g) => GEmptyZohoStructure (f :*: g) where
gEmptyZohoStructure = (gEmptyZohoStructure :: f p) :*: (gEmptyZohoStructure :: g p)
instance GEmptyZohoStructure Maybe where
gEmptyZohoStructure = Nothing
class EmptyZohoStructure a where
emptyZohoStructure :: a
default emptyZohoStructure :: (Generic a, (GEmptyZohoStructure (Rep a))) => a
emptyZohoStructure = GHC.Generics.to gEmptyZohoStructure
-- Whereas these parts are random type-class instances that I've written, just
-- to get the code to compile.
instance (GEmptyZohoStructure f) => GEmptyZohoStructure (M1 i t f) where
gEmptyZohoStructure = (gEmptyZohoStructure :: f p)
instance (GEmptyZohoStructure f) => GEmptyZohoStructure (K1 i (f p)) where
gEmptyZohoStructure = gEmptyZohoStructure
instance EmptyZohoStructure Approval
代码编译时,以下(可以理解)导致运行时堆栈溢出:
ghci> emptyZohoStructure :: Approval
*** Exception: stack overflow
我正在按照 https://www.stackage.org/haddock/lts-12.1/base-4.11.1.0/GHC-Generics.html#g:12 给出的 encode
教程进行操作,其中由于参数被传递给 encode
函数,它允许人们有机会解包 M1
/ K1
构造函数并构建一些有意义的递归层次结构。 如何为 M1
和 K1
的用例编写泛型(泛型函数实际上没有任何参数)?
在类型类中为泛型定义 GEmptyZohoStructure Maybe
毫无意义。
class G f where
gempty' :: f p
instance (G f, G g) => G ( f :*: g) where
gempty' = gempty' :*: gempty'
instance G c => G (D1 x c) where
gempty' = M1 gempty'
instance G s => G (C1 x s) where
gempty' = M1 gempty'
instance E t => G (S1 m (Rec0 t)) where -- the key instance
gempty' = M1 (K1 gempty)
class E a where
gempty :: a
default gempty :: (Generic a, G (Rep a)) => a
gempty = to gempty'
instance E (Maybe a) where
gempty = Nothing
之后,您可以定义任何由 Maybe 值组成的产品类型。
我正在为 Zoho REST API 编写一个客户端库,并且有一堆不同的记录类型,它们具有所有 Maybe a
个字段,即:
data Approval = Approval
{ apDelegate :: Maybe Bool
, apApprove :: Maybe Bool
, apReject :: Maybe Bool
, apResubmit :: Maybe Bool
} deriving (Eq, Show, Generic)
data ContactSpecialFields = ContactSpecialFields
{ csfCurrencySymbol :: Maybe Text -- $currency_symbol
, csfState :: Maybe Text -- $state
, csfProcessFlow :: Maybe Bool -- $process_flow
, csfApproved :: Maybe Bool -- $approved
, csfApproval :: Approval -- $approval
, csfEditable :: Maybe Bool -- $editable
} deriving (Eq, Show)
-- and so on
我需要一种方法来定义 "empty" 这种类型的记录,例如:
emptyApproval :: Approval
emptyApproval = Approval
{ apDelegate = Nothing
, apApprove = Nothing
, apReject = Nothing
, apResubmit = Nothing
}
因此,我联系了 GHC.Generics
并得到了一些有用的东西(这是错误的!):
-- These parts seem logically correct to me...
class GEmptyZohoStructure f where
gEmptyZohoStructure :: f p
instance (GEmptyZohoStructure f, GEmptyZohoStructure g) => GEmptyZohoStructure (f :*: g) where
gEmptyZohoStructure = (gEmptyZohoStructure :: f p) :*: (gEmptyZohoStructure :: g p)
instance GEmptyZohoStructure Maybe where
gEmptyZohoStructure = Nothing
class EmptyZohoStructure a where
emptyZohoStructure :: a
default emptyZohoStructure :: (Generic a, (GEmptyZohoStructure (Rep a))) => a
emptyZohoStructure = GHC.Generics.to gEmptyZohoStructure
-- Whereas these parts are random type-class instances that I've written, just
-- to get the code to compile.
instance (GEmptyZohoStructure f) => GEmptyZohoStructure (M1 i t f) where
gEmptyZohoStructure = (gEmptyZohoStructure :: f p)
instance (GEmptyZohoStructure f) => GEmptyZohoStructure (K1 i (f p)) where
gEmptyZohoStructure = gEmptyZohoStructure
instance EmptyZohoStructure Approval
代码编译时,以下(可以理解)导致运行时堆栈溢出:
ghci> emptyZohoStructure :: Approval
*** Exception: stack overflow
我正在按照 https://www.stackage.org/haddock/lts-12.1/base-4.11.1.0/GHC-Generics.html#g:12 给出的 encode
教程进行操作,其中由于参数被传递给 encode
函数,它允许人们有机会解包 M1
/ K1
构造函数并构建一些有意义的递归层次结构。 如何为 M1
和 K1
的用例编写泛型(泛型函数实际上没有任何参数)?
在类型类中为泛型定义 GEmptyZohoStructure Maybe
毫无意义。
class G f where
gempty' :: f p
instance (G f, G g) => G ( f :*: g) where
gempty' = gempty' :*: gempty'
instance G c => G (D1 x c) where
gempty' = M1 gempty'
instance G s => G (C1 x s) where
gempty' = M1 gempty'
instance E t => G (S1 m (Rec0 t)) where -- the key instance
gempty' = M1 (K1 gempty)
class E a where
gempty :: a
default gempty :: (Generic a, G (Rep a)) => a
gempty = to gempty'
instance E (Maybe a) where
gempty = Nothing
之后,您可以定义任何由 Maybe 值组成的产品类型。