使用模板Haskell生成带有帮助的新类型包装器



我有一个非常简单的用例,我有一个基本类型,但为了在我的数据模型中我的各种记录类型的目的,我希望每个记录都有这种类型的包装版本:

type UID = Integer
-- specialised version
newtype MyRecordID = MyRecordID UID
-- constructor which can take any integral type because I get 
-- Int32 from the database and it's a lot of annoying
-- boilerplate each time
myRecordID :: Integral a => a -> MyRecordID
myRecordID = MyRecordID . fromInteger

有一些这样的记录,而不是每次手工编写这些构造函数,我认为这可能是使用TH的理想方式。

从这个答案,我设法使newtype声明(虽然它真的困扰我,有很多我不明白在这):

wrapUID :: String -> Q [Dec]
wrapUID n = (:[]) <$> dataD (cxt []) 
name
[]
Nothing
[normalC name 
[bangType (bang noSourceUnpackedness noSourceStrictness)
[t| UID |]]]
[]
where name = mkName n

我不知道如何创建"构造器"声明。

如果您满足于重用现有的解决方案而不是编写自己的解决方案,您可以使用product-profunctors

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.Profunctor.Product.TH
import Data.Profunctor.Product.Newtype
type UID = Integer
newtype MyRecordID' a = MyRecordID a
type MyRecordID = MyRecordID' UID
$(makeAdaptorAndInstanceInferrable "pMyRecordID" ''MyRecordID')
myAnything :: (Newtype t, Integral a) => a -> t a
myAnything = constructor . fromIntegral

相关内容

  • 没有找到相关文章

最新更新