Skip to content
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

mkYesodGeneral: Argument types can now be polymorphic #1055

Merged
merged 5 commits into from Aug 16, 2015

Conversation

Projects
None yet
3 participants
@Daniel-Diaz
Copy link
Contributor

Daniel-Diaz commented Aug 11, 2015

PR related with #1051.

Summary

I made some changes to mkYesodGeneral, so that it is possible to create sites with polymorphic type parameters.

Type change

The type of mkYesodGeneral has changed from String -> [String] -> Bool -> [ResourceTree String] -> Q ([Dec],[Dec]) to String -> [Either String [String]] -> Bool -> [ResourceTree String] -> Q ([Dec],[Dec]). The [String] argument was used to pass monomorphic type arguments to the type named by the first argument. In the new function, you can either specify a monomorphic type (using Left) or a polymorphic type (using Right). The list of Strings represents a list of classes that will be added to the context of the YesodDispatch instance.

I know this might seem confusing, but I thought it was the closest way to achieve what I wanted without making substantial changes. Plus, everything that worked before, should still work without changes.

Example

An example to explain how the new mkYesodGeneral works:

data Foo a = Foo a

class Bar a where
  ...

mkYesodWith "Foo" [Right ["Bar"]] (...)

This would create Yesod types and instances for the type Foo, and the YesodDispatchclass would look like:

instance Bar a => YesodDispatch (Foo a) where
   ...

The Handler will be parametrized too:

getSomethingR :: Handler a x
getSomethingR = ...

If you write a route handler like:

getSomethingElseR :: Bar a => Handler a x
getSomethingElseR = ...

Since the Bar a constraint has been added to the YesodDispatch instance context, it won't fail because a missing instance.

Note that the type variable of polymorphic parameters is not given by the user, but automatically generated by mkYesodGeneral.

Other considerations

  • The Either type is a little obscure, in the sense that it doesn't really tell us much about the intention of the argument. In the first place I considered defining a new type to make the intention of the argument clearer. I failed to the Either side because I wanted to make as little changes as possible.
  • New mkYesodGeneral uses a very simple pattern match to deduce the arity of the site type. This has flaws. For example, it doesn't see through type synonyms, which will consider of arity 0. In any case, this means that for many cases it will just work as it has been working before.
  • A new function mkYesodWith was added in the spirit of mkYesod, but with an additional argument to pass type parameters (either monomorphic or polymorphic). The name was chosen arbitrarily and can be changed to any other.
  • In issue #1051 was suggested to make mkYesodGeneral arguments be of type Name instead of String, which probably makes sense, but I didn't want to do it just yet.

Epilogue

Please, let me know any changes that are needed to get this functionality merged. I need it for a server I'm writing where the site type is parametrized. This shouldn't affect any yesod users as mkYesod will behave exactly the same way for traditional use cases. This change will only make possible to compile more cases.

Thanks!

@creichert

This comment has been minimized.

Copy link
Member

creichert commented Aug 11, 2015

Can you outline a specific use-case for this? (I'm not doubting it's useful but I am curious).

Assuming there are no other issues, it would also be nice to have some form of a test case for the exposed function (something similar to the WaiSubsiteTest).

@creichert

This comment has been minimized.

Copy link
Member

creichert commented Aug 11, 2015

Direct link to build issue on ghc 7.8: https://travis-ci.org/yesodweb/yesod/jobs/75128065#L1367

@Daniel-Diaz

This comment has been minimized.

Copy link
Contributor Author

Daniel-Diaz commented Aug 11, 2015

@creichert My current use-case involves a shared state (implemented as a mutable reference in the site type) with a Map, where the keys (maybe elements too) of the map are different in different instances of the server. The types are decided from a configuration file at run time.

The build failure seems to be related with the GHC version used by travis. I'll see how to make it compatible with versions of GHC previous to 7.10.

@Daniel-Diaz

This comment has been minimized.

Copy link
Contributor Author

Daniel-Diaz commented Aug 11, 2015

Compilation problems solved.

@gregwebs

This comment has been minimized.

Copy link
Member

gregwebs commented Aug 16, 2015

This is good, but it looks like a breaking change. Is it possible to export a new function (perhaps YesodPolymorphic) and maintain the old interface?

@Daniel-Diaz

This comment has been minimized.

Copy link
Contributor Author

Daniel-Diaz commented Aug 16, 2015

@gregwebs Please, can you tell me how this is a breaking change? As far as I know, mkYesodGeneral is not exported to the user.

Thanks!

@gregwebs

This comment has been minimized.

Copy link
Member

gregwebs commented Aug 16, 2015

ahh, ok

gregwebs added a commit that referenced this pull request Aug 16, 2015

Merge pull request #1055 from Daniel-Diaz/master
mkYesodGeneral: Argument types can now be polymorphic

@gregwebs gregwebs merged commit 0fdb78a into yesodweb:master Aug 16, 2015

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.