I wrote a web application using scotty and acid state, now i would like to use type classes to be able to provide alternative implementations for the capabilities of my application for testing. I get the general idea of it and am able to apply it so simple examples but since im am using acid state there are a lot of type classes and template haskell involved which i am not entirely comfortable with yet.
so i have these straight-forward classes for the different capabilities
class Logging m where
log :: T.Text -> m ()
class Server m where
body :: m B.ByteString
respond :: T.Text -> m ()
setHeader :: T.Text -> T.Text -> m ()
class Db m where
dbQuery :: (MethodState event ~ Database,QueryEvent event) => event -> m (EventResult event)
dbUpdate :: (MethodState event ~ Database,UpdateEvent event) => event -> m (EventResult event)
and i also provided instances for them for my "production" monad.
But when it comes to the database capability i cant get to work what i want.
the class looks like this
class Db m where
dbQuery :: (MethodState event ~ Database,QueryEvent event) => event -> m (EventResult event)
dbUpdate :: (MethodState event ~ Database,UpdateEvent event) => event -> m (EventResult event)
and the instance for the production monad works fine since it only passes the event to the update and query functions of acid state, but for a test monad i would like to have something like this: instance Db Test where dbQuery (GetVersion) = use (testDb . clientVersion) dbQuery (GetUser name) = preuse (testDb . users . ix name) dbUpdate (PutUser name user) = users %= M.insert name user ... so that I can match on GetVersion,GetUser etc. (which are generated by the template haskell function makeAcidic ... ) and specify how they should be handled in the test environment.
But I get the error:
Could not deduce: event ~ GetVersion
from the context: (MethodState event ~ Database, QueryEvent event)
bound by the type signature for:
dbQuery :: (MethodState event ~ Database, QueryEvent event) =>
event -> Test (EventResult event)
at Main.hs:88:3-9
‘event’ is a rigid type variable bound by
the type signature for:
dbQuery :: forall event.
(MethodState event ~ Database, QueryEvent event) =>
event -> Test (EventResult event)
at Main.hs:88:3
• In the pattern: GetVersion
In an equation for ‘dbQuery’:
dbQuery (GetVersion) = use (testDb . clientVersion)
In the instance declaration for ‘Db Test’
• Relevant bindings include
dbQuery :: event -> Test (EventResult event)
(bound at Main.hs:88:3)
i guess thats because GetVersion, GetUser etc. all have a their different own types. So is there a way to do this?
Aucun commentaire:
Enregistrer un commentaire