On 10/01/2013 07:58 AM, Michael Snoyman wrote: > I'm wondering if anyone's run into this problem before, and if there's a > common solution. > > In Yesod, we have applicative forms (based originally on formlets). > These forms are instances of Applicative, but not of Monad. Let's > consider a situation where we want to get some user input to fill out a > blog post datatype, which includes the current time: > > data Blog = Blog Title UTCTime Contents > > myBlogForm :: Form Blog > myBlogForm = Blog <$> titleForm <*> something <*> contentsForm > > The question is: what goes in something? Its type has to be: > > something :: Form UTCTime > > Ideally, I'd call getCurrentTime. The question is: how do I lift that > into a Form? Since Form is only an Applicative, not a Monad, I can't > create a MonadIO instance. However, Form is in fact built on top of > IO[1]. And it's possible to create a MonadTrans instance for Form, since > it's entirely possible to lift actions from the underlying functor/monad > into Form. So something can be written as: > > something = lift $ liftIO getCurrentTime
Is it really necessary to have a type class to do this? You can always just introduce 'io :: IO a -> Form a' to lift IO actions into a form. Then you just have: myBlogForm = Blog <$> titleForm <*> io getCurrentTime <*> contentsForm In digestive-functors, we have the base monad in the type of the form itself, so we provide 'monadic' which goes from m (Form m a) -> Form m a (hand-waving as there are actually other type constraints). You might get more power by following in those steps, and having the aforementioned 'io' function actually be: io :: IO (Form a) -> Form a - ocharles
signature.asc
Description: OpenPGP digital signature
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe