我想在Haskell中實現一個DelayedJob(來自Rails世界)的端口。如何在運行時將對應的Haskell類型可用的JSON反序列化爲值?
這裏的類型類我有代表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
功能,而不必寫了這麼多的樣板?
不回答你的問題,但不應該定義'serialize'和'deserialize'函數,因爲它們似乎只能有一個實現,它是從約束派生的。 – bartavelle