-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/mtl refactor #18
base: master
Are you sure you want to change the base?
Conversation
I meant to keep this library as simple as possible (and show how good haskell is, even when not using fancy extensions), but on the other hand, mtl is such a major design that is worth learning so I'm ok to merge this. For the tutorial purpose, I wonder if we could expose a withSession <- createWithSession "https://matrix.org" token
Right userId <- withSession getTokenOwner Similarly, it might be good to expose a Otherwise, I also think this cleans things up nicely, thanks you! |
I get where you are coming from and I don't think we should go too crazy with the library. I think its good to treat it as a fairly low level binding to the Matrix REST API that doesn't do anything too magical. I think Monad Transformers are standard enough that its reasonable to use them here. Its really nice to not have to thread the |
how do this look? createWithSession ::
-- | The matrix client-server base url, e.g. "https://matrix.org"
T.Text ->
-- | The user token
MatrixToken ->
-- | The matrix action to perform
MatrixIO a ->
IO (Either MatrixError a)
createWithSession baseUrl' token' action = do
session <- createSession baseUrl' token'
runMatrixIO session action Or should we make it polymorphic on the createWithSession ::
MonadIO m =>
-- | The matrix client-server base url, e.g. "https://matrix.org"
T.Text ->
-- | The user token
MatrixToken ->
-- | The matrix action to perform
MatrixM m a ->
m (Either MatrixError a)
createWithSession baseUrl' token' action = do
session <- liftIO $ createSession baseUrl' token'
runMatrixM session action We can have both i suppose: createWithSessionIO ::
-- | The matrix client-server base url, e.g. "https://matrix.org"
T.Text ->
-- | The user token
MatrixToken ->
-- | The matrix action to perform
MatrixIO a ->
IO (Either MatrixError a)
createWithSessionIO = createWithSession |
I'm not sure how this would work, or I am misunderstanding the idea. |
Thank you for the update, I'll give this a try and update the tutorial. My suggestions are mostly for basic ghci usage, where previously you would do: > sess <- createSession "https://matrix.org" token
> Right room <- joinRoom sess "#test"
> sendMessage sess room message With the > withSession <- createWithSession "https://matrix.org" token
> Right room <- withSession $ joinRoom "#test"
> withSession $ sendMessage room message Thus I think it should return a callback, otherwise it seems like it would re-create the manager each time: createWithSession ::
MonadIO m =>
-- | The matrix client-server base url, e.g. "https://matrix.org"
T.Text ->
-- | The user token
MatrixToken ->
-- | The matrix action to perform
m (MatrixM m a -> m (Either MatrixError a))
createWithSession baseUrl' token' = do
session <- liftIO $ createSession baseUrl' token'
pure $ \action -> runMatrixM session action Well, otherwise I'm not sure how the Tutorial module can be updated. And since we are updating the library API, I think it would be better to add the http manager to the argument of If that sounds good to you, I can add the change to the PR later. |
In the event a MatrixError is expected, it seems like the ExceptT is going to shortcut the user defined action unless |
Change-Id: I38b990955c3bd4b9126388bd3f40591fceb4c232
cf9e459
to
4b806ab
Compare
Here is a rebase to include the loginToken. I'll now update the tutorial and propose adding the Manager to the login/createsSession arguments. |
This change enables running doctest as part of the test-suite. Change-Id: Ic78759fbf5b105e3c9c74b764b10b97b7c7a3a6d
98cb5aa
to
fea8f1b
Compare
Sorry about the createWithSession suggestion, I was able to update the Tutorial without it, and with hindsight, it may not be useful. My last remaining concern is the 'login' function which I would like to change to a withLogin to force the logout call on exit. But that could be done in a separate PR. If that is ok with you, then I think we should merge this. Thanks again for doing the refactor. |
Change-Id: Iaa4110faa1737e0395de86ef5ebeb9f4af1a95c7
Change-Id: I64106c117ca5f7dc3832f6e731e67d5b4dcbafb6
Change-Id: I6837a8ae00f4f622645a90e024a2bd8666ba19a9
When running doctest outside of a nix-shell, it is failing to find build depends. Change-Id: I7aaa4e9f1f4b656ca76003643a98aaf04b1d07b4
fea8f1b
to
603fc7d
Compare
This change removes the custom IdentitySession in favor of the existing ClientSession so that the runMatrixIO can be used for both clients. Change-Id: I07af2395ecc6b1f76eefe86215952c48edcacc55
ClientSession {..} <- ask | ||
MatrixM $ ExceptT $ liftIO $ doRequest' manager request | ||
|
||
newtype MatrixM m a = MatrixM { unMatrixM :: ExceptT MatrixError (ReaderT ClientSession m) a } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO we'd better call this MatrixT
as it's a monad transformer. Also, we can have a interface like:
class MonadMatrix m where
getClientSession :: m ClientSession
throwMatrixError :: MatrixError -> m a
performHttpRequest :: FromJSON a => HTTP.Request -> m a
Then MatrixT
could be a default implementation of MonadMatrix
:
instance MonadIO m => MonadMatrix (MatrixT m) where
getClientSession = ask
throwMatrixError = throwError
performHttpRequest = ...
and users may create their own monads with or wihout MatrixT
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presently, this is going to be tricky when using both a regular session and a identity session, I think we need to implement a ClientSession that support both endpoints, otherwise I think it's going to be tricky to implement such Monad for both use-case.
I haven't worked on this project in a while but I should have some time coming up in a few weeks. Is there anything y'all would like me to do to assist here? |
I guess changing the name from MatrixM to MatrixT is reasonable, though I don't get what's the benefit of having a MonadMatrix class, e.g. I find the 'throwMatrixError' method confusing. Thanks @solomon-b, would you have time to rebase the PR? |
In the CHANGELOG, I would add a migration note, something like:
It's also a bit annoying that the Identity API requires a different token and the present type doesn't prevent using the wrong session. I guess we could tag the Session and/or include both token... |
I wanted to see what the API would look like if converted to a monad transformer stack. I think it cleans things up quite nicely. What do you think? If we decide to merge this, I'll definitely add more docs.