我正在尝试在 Haskell 中实现一个 DelayedJob 端口(来自 Rails 世界)。
这是我拥有的类型类,它代表一个DelayedJob
class (FromJSON j, ToJSON j, FromJSON r, ToJSON r) => DelayedJob j r | j -> r where
serialise :: j -> Value
serialise = toJSON
deserialise :: Value -> Either String j
deserialise = parseEither parseJSON
runJob :: j -> AppM r
以下是我打算如何使用它:
createJob :: (DelayedJob j r) => j -> AppM JobId
我一直在编写一个相当通用的invokeJob
函数,该函数将从jobs
表中读取一行,查看jobs.jobtype
列并调用版本的正确runJob
版本(即runJob
属于正确类型类实例的函数)。
我有以下内容,但它充满了样板:
data JobType = SyncContacts | SendEmail | SendSms deriving (Eq, Show, Generic)
invokeJob :: JobId -> AppM ()
invokeJob jid = do
job <- fetchJob jid
case (job ^. jobtype) of
SyncContacts -> case (deserialise (job ^. jobdata) :: Either String SynContactsJob) of
Left e -> error e
Right j -> storeJobResult jid $ runAppM j
SendEmail -> case (deserialise (job ^. jobdata) :: Either String SendEmailJob) of
Left e -> error e
Right j -> storeJobResult jid $ runAppM j
SendSms -> case (deserialise (job ^. jobdata) :: Either String SendSms) of
Left e -> error e
Right j -> storeJobResult jid $ runAppM j
本质上,有没有办法deserialise
在运行时动态地约束函数的具体类型,而不必编写这么多样板文件?