Mark Karavan
Mark Karavan

Reputation: 2674

aform types in Yesod

I've been following this tutorial for learning Yesod, and am trying to run this simple form:

{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE QuasiQuotes                #-}
{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE TemplateHaskell            #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE ViewPatterns               #-} 
import Control.Applicative((<$>),(<*>))
import Yesod

data App = App

mkYesod "App" [parseRoutes|
/accum Accum GET
|]

instance Yesod App

instance RenderMessage App FormMessage where
   renderMessage _ _ = defaultFormMessage

data Info = Info 
   { deposit :: Double
   , rate    :: Double
   , years   :: Double
   }

aform :: AForm App App Info
aform = Info
   <$> areq doubleField "Deposit" Nothing
   <*> areq doubleField "Rate" Nothing
   <*> areq doubleField "Years" Nothing

accum x = deposit x * (1 + rate x * years x)

mform = renderTable aform

getAccum :: Handler RepHtml
getAccum = do
   ((result, widget), enc) <- runFormGet mform
   case result of
      FormSuccess info -> defaultLayout [whamlet|<p> #{show (accum info)} |]
      _                -> defaultLayout [whamlet| 
      <form method=get action=@{Accum} enctype=#{enc}>
         <table>
            ^{widget}
         <input type=submit>
         |]

main = warpDebug 2012 App

When I runhaskell forms.hs, I get this error:

forms.hs:27:10:
    ‘AForm’ is applied to too many type arguments
    In the type signature for ‘aform’: aform :: AForm App App Info

After futzing with a number of variations of the type signature, I kept getting errors. The ghci :info AForm reads

Prelude Yesod> :info AForm
type role AForm nominal nominal
newtype AForm (m :: * -> *) a

But a change to aform :: AForm (App -> App) Info gives me this error:

forms.hs:27:17:
    The first argument of ‘AForm’ should have kind ‘* -> *’,
      but ‘App -> App’ has kind ‘*’

Any ideas on how to resolve this?

Upvotes: 0

Views: 83

Answers (1)

Michael Snoyman
Michael Snoyman

Reputation: 31355

The type signature for areq is:

areq :: (RenderMessage site FormMessage, HandlerSite m ~ site, MonadHandler m) => Field m a -> FieldSettings site -> Maybe a -> AForm m a

Note how it takes two parameters, and the first parameter is an instance of MonadHandler. Therefore, your signature on aform will need to have the same parameter. In your code, this may look like:

aform :: AForm (HandlerT App IO) Info

or the shortened form:

aform :: AForm Handler Info

Have a look at the car example in the Yesod book.

Upvotes: 1

Related Questions