Haskell

The meeting place for professional Haskell programmers
You are not logged in. In order to participate in Special Interest Groups, you should log in now .

Intimidating GFormMonad type errors (Discussion)

Created by Steven Robertson on November 12, 2010 08:31:01 PM.
Status: Open

Messages

By Steven Robertson @ November 12, 2010 08:51:31 PM

I'm no longer entirely Haskell-incompetent, but in a current Yesod project which requires complex forms, I'm still liable to make a type error or two. Whereupon GHC gives this friendly message:

Handler/Activity.hs:90:0:
    Couldn't match expected type `Maybe String'
           against inferred type `FormType
                                    (Control.Monad.Trans.Writer.Lazy.WriterT
                                       Enctype
                                       (Yesod.Form.Core.FormInner s m)
                                       ([Maybe String], FieldInfo s m))'
      NB: `FormType' is a type function, and may not be injective
    When generalising the type(s) for `modActivityForm'

Handler/Activity.hs:102:14:
    Could not deduce (IsForm
                        (Control.Monad.Trans.Writer.Lazy.WriterT
                           Enctype
                           (Yesod.Form.Core.FormInner s m)
                           ([Maybe String], FieldInfo s m)))
      from the context ()
      arising from a use of `maybeStringField'
                   at Handler/Activity.hs:102:14-56
    Possible fix:
      add (IsForm
             (Control.Monad.Trans.Writer.Lazy.WriterT
                Enctype
                (Yesod.Form.Core.FormInner s m)
                ([Maybe String], FieldInfo s m))) to the context of
        the type signature for `modActivityForm'
      or add an instance declaration for
         (IsForm
            (Control.Monad.Trans.Writer.Lazy.WriterT
               Enctype
               (Yesod.Form.Core.FormInner s m)
               ([Maybe String], FieldInfo s m)))
    In the first argument of `(.)', namely
        `maybeStringField "Held resource to release"'
    In the first argument of `mapM', namely
        `(maybeStringField "Held resource to release" . Just)'
    In the second argument of `($)', namely
        `mapM
           (maybeStringField "Held resource to release" . Just)
           (take 5 $ marelNames ++ repeat Nothing)'

Handler/Activity.hs:90:0:
    Couldn't match expected type `Maybe String'
           against inferred type `FormType
                                    (Control.Monad.Trans.Writer.Lazy.WriterT
                                       Enctype
                                       (Yesod.Form.Core.FormInner s m)
                                       (FormResult ActivityResourceRelease, FieldInfo s m))'
      NB: `FormType' is a type function, and may not be injective
    When generalising the type(s) for `modActivityForm'

Often, the actual line of code with the nonsensical type signature isn't even listed as having an error.

After a day of poking around, I figured out that the error was in my own code, and simply appeared to be coming from the *Field functions. However, as is my habit when I suspect a type error in my code, I commented out most of my code, added dummy return types, and loaded the module into GHCi to inspect the return types... and got what looked like the same error!

I now understand that this message is a result of improper or insufficient constraints on the IsForm typeclass functions (or something along those lines), but discovering this on my own was painful. Any way this situation can result in less-intimidating error messages?

By Michael Snoyman @ November 13, 2010 04:22:18 PM

You're absolutely correct that these error messages are intimidating. It would be wonderful to figure out a better way to provide the form polymorphism. (By the way, the same applies to Hamlet polymorphism: error messages can get scary there too.)

Unfortunately, I don't know of a way to handle this right now. Maybe I'll play around with some ideas, such as limiting the scope of the polymorphism. Sounds like something that might come out in a 0.7 release, if one happens.

Login with