Overall context: I'm trying to port the DelayedJob library from Ruby/Rails world to Haskell. The basic idea is to serialise a job and write it to the DB, deserialise it, and run the job using a job-runner function, which is determined by the job-type.
I'm using a type-class to define the custom job-runner, something on the lines of:
class (FromJSON j, ToJSON j) => DelayedJob j where
runJob :: j -> AppM ()
data SyncContactsJob = SyncContactsJob { userId :: UserId } deriving (Eq, Show, Generic, FromJSON, ToJSON)
instance DelayedJob SyncContactsJob where
runJob job = do
-- entire job execution logic comes here
Is there **any** type-system hackery, that will let me take a runtime value, eg. "SyncContactsJob", "DoBackupJob", and use that to run the correct version of the `runJob` function? That is, how do I write the following function:
invokeJob :: JobId -> AppM ()
invokeJob jid = do
jobRow <- fetchJob jid
let jtype = jobRow ^. jobtype -- this will have "SyncContactsJob"
jvalue = jobRow ^. jobdata -- this will have a Data.Aeson.Value
runJob (......) -- QUESTION: What do I write here to make this compile?