1

Context

In a controller, I have a function that is called via beforeAction to check if a certain field on user is null or not. If it is null, the user should be redirected to a certain action in another controller.

Since I want to call this function from almost every controller in my application, putting it in Application.Helper.Controller seems the right choice, but I cannot figure out the type signature.

The function is as follows, and in a normal controller this works:

ensureIsSubscribed :: _ => IO ()
ensureIsSubscribed = do
    case currentUserOrNothing of
        Just loggedInUser -> do
            case (get #subscriptionId loggedInUser) of
                Nothing -> redirectToPath "/NewCheckoutSession"
                _ -> redirectToPath "/Welcome"
        Nothing -> pure ()

but when putting the above in Application.Helper.Controller I get this error:

• Could not deduce (HasField
                      "subscriptionId" CurrentUserRecord (Maybe a0))
    arising from a use of ‘get’
  from the context: ?context::ControllerContext
    bound by the inferred type of
               ensureIsSubscribed :: (?context::ControllerContext) => IO ()
    at Application/Helper/Controller.hs:(8,1)-(14,26)
  The type variable ‘a0’ is ambiguous
• In the expression: (get #subscriptionId loggedInUser)
  In a stmt of a 'do' block:
    case (get #subscriptionId loggedInUser) of
      Nothing -> redirectToPath "/NewCheckoutSession"
      _ -> redirectToPath "/Welcome"
  In the expression:
    do case (get #subscriptionId loggedInUser) of
         Nothing -> redirectToPath "/NewCheckoutSession"
         _ -> redirectToPath "/Welcome"
   |
11 |             case (get #subscriptionId loggedInUser) of
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Question

Why does the above not work and what is the correct type signature (if that is the problem)?

  • Try to fix ambiguous of type variable `a0`. Change `_ -> redirectToPath "/Welcome"` to `Just (_ :: ProperType) -> redirectToPath "/Welcome"` where `ProperType` is type of subscription ID (I don't known it). – freestyle Oct 05 '21 at 10:30
  • Basically, It's look like `CurrentUserRecord` hasn't field `subscriptionId`. – freestyle Oct 05 '21 at 10:37
  • Thank you for your suggestions! The fix lay in another direction (see the answer below). – stephenbenedict Oct 14 '21 at 10:09

1 Answers1

1

The CurrentUserRecord is defined in Web/Types.hs as type instance CurrentUserRecord = User. If the Web.Types module is not imported, the type CurrentUserRecord cannot be replaced with it's definition User.

The fix is therefore to add an import Web.Types to your Application.Helper.Controller module :)

Marc Scholten
  • 1,351
  • 3
  • 5
  • Thanks! I actually tried that before since I guessed that might be the problem but it does not solve the error which is now: `Could not deduce (HasField "subscriptionId" Generated.Types.User (Maybe a0)) arising from a use of ‘get’ from the context: ?context::ControllerContext` – stephenbenedict Oct 07 '21 at 02:52
  • Can you add an `import Generated.Types`? Maybe the User type is not in scope. – Marc Scholten Oct 07 '21 at 05:28
  • Thank you! Adding the import Generated.Types was the final key to the solution! – stephenbenedict Oct 13 '21 at 14:30