
On Tue, Feb 22, 2011 at 12:08 PM, Dmitry Kurochkin
On Mon, 21 Feb 2011 07:23:56 +0200, Michael Snoyman
wrote: On Sun, Feb 20, 2011 at 11:04 PM, Dmitry Kurochkin
wrote: Hi Michael.
On Sun, 13 Feb 2011 19:13:06 +0300, Dmitry Kurochkin
wrote: On Sun, 13 Feb 2011 17:44:33 +0200, Michael Snoyman
wrote: On Sun, Feb 13, 2011 at 5:28 PM, Dmitry Kurochkin
wrote: Still the argument remains. I want to have all menu-related code in a separate module.
OK. As I said, this is possible, and it sounds like you already got 90% of the way there. I don't know what's holding you up until I see your code. My initial reaction is still that this is a bad idea in general, though I *am* reconsidering that position. It might make sense to alter the approach used by the scaffolded site.
I will try to send you some an example later. Unfortunately, I do not have time for this right now. Playing with Yesod in my free time only.
I took another look at it. Turns out my problem was caused by using getCurrentRoute in the widget. If there is no getCurrentRoute, it works fine and I can use the widget in the defaultLayout.
Here is a simple code to demonstrate the issue:
testWidget :: GWidget sub Test () testWidget = do Just route <- lift getCurrentRoute addWidget [$hamlet|@{route}|]
Add the above code to the main application module. In the above case Test is the foundation type. I get the following error:
Couldn't match expected type `TestRoute' against inferred type `Route sub' NB: `Route' is a type function, and may not be injective
I would appreciate if you explain what the problem is and how to solve it.
getCurrentRoute[1] returns a route for the current subsite, while you want a route for Test (ie, Route sub vs Route Test). You need to convert your Route sub into a Route Test, by using getRouteToMaster[2].
Thank you! The following works:
testWidget :: GWidget sub Test () testWidget = do Just route <- lift getCurrentRoute routeToMaster <- lift getRouteToMaster addWidget [$hamlet|@{routeToMaster route}|]
Perhaps a getCurrentMasterRoute function would be useful? Though I am not sure how common is my case.
If you look through Yesod.Handler, there are a number of functions that are duplicated for sub and master sites. I had to choose which one would get the shorter name, and made a call based on my information at the time. However, I've wondered many times if I made the wrong choice on some of them. I think it would be a good idea to revisit all of those decisions before the 1.0 release: making those changes *will* break code, but not in any significant way. This would probably be a good candidate for change.
So look like the only real issue with putting widgets for defaultLayout to a separate module is separating mkYesodData and Yesod instance. You were talking about orphan Yesod instance, is it some kind of dummy instance declaration that would allow widgets to use Yesod instance without importing the actual module that defines it?
Nothing magical, it *should* be possible to just move the Yesod instance into a separate module. However, you'll likely get a cascade of error messages which you will need to fix by either moving code around or changing the type signature to work for any instance of Yesod. Plus you'll need to make sure that all your handler code imports that separate module. In other words: you can achieve this, but you'll be going into slightly uncharted territory. I give no guarantees that it won't make your code worse. Michael
Regards, Dmitry
Michael
[1] http://hackage.haskell.org/packages/archive/yesod-core/0.7.0.1/doc/html/Yeso... [2] http://hackage.haskell.org/packages/archive/yesod-core/0.7.0.1/doc/html/Yeso...