Context/signature mismatch when using dynamic functions in Reflex-DOM

39 views Asked by At

I was able to get this dropdown compiling:

bodyElementPracticeType :: MonadWidget t m => m ()
bodyElementPracticeType = el "div" $ do
  el "h2" $ text "Dropdown"
  text "Select sport "
  dd <- dropdown Solo_Workout (constDyn (Map.fromList [(e, showSoloPersonPracticeType e) | e <- [minBound..]])) def
  el "p" $ return ()
  let selItem = result <$> value dd 
  dynText selItem 

result :: SoloPersonPracticeType -> T.Text
result e = fromJust $ Map.lookup e $ Map.fromList [(e, showSoloPersonPracticeType e) | e <- [minBound..]]

data SoloPersonPracticeType = 
        Solo_Workout 
    |   Solo_Run

showSoloPersonPracticeType :: SoloPersonPracticeType -> T.Text 
showSoloPersonPracticeType = \case 
    Solo_Workout -> T.pack "Workout"
    Solo_Run -> T.pack "Run"

deriving instance Enum SoloPersonPracticeType 
deriving instance Bounded SoloPersonPracticeType 
deriving instance Eq SoloPersonPracticeType 
deriving instance Ord SoloPersonPracticeType 

instance Universe SoloPersonPracticeType where 
    universe = [minBound..]

But I am working within Obelisk's framework, so I have tried some modifications to put the widget within the structure specified there:

frontend :: Frontend (R FrontendRoute)
frontend = Frontend
  { _frontend_head = do
      el "title" $ text "The App Name"
      elAttr "link" ("href" =: static @"bulma.css" <> "type" =: "text/css" <> "rel" =: "stylesheet") blank
  , _frontend_body = subRoute_ $ \case 
        FrontendRoute_Main -> do
            -- bodyElementPracticeType :: MonadWidget t m => m ()
            let bodyElementPracticeType = el "div" $ do
                el "h2" $ text "Dropdown"
                text "Select sport "
                dd <- dropdown Solo_Workout (constDyn (Map.fromList [(e, showSoloPersonPracticeType e) | e <- [minBound..]])) def
                el "p" $ return ()
                let selItem = result <$> value dd 
                dynText selItem 

                -- result :: SoloPersonPracticeType -> T.Text
                let result e = fromJust $ Map.lookup e $ Map.fromList [(e, showSoloPersonPracticeType e) | e <- [minBound..]]
                       return ()
  }

But I am getting this error:

frontend/src/Frontend.hs:184:17-125: error:
    The last statement in a 'do' block must be an expression
      let result e
            = fromJust $ Map.lookup e
                $ Map.fromList
                    [(e, showSoloPersonPracticeType e) | e <- [minBound .. ]]
    |
184 |                 let result e = fromJust $ Map.lookup e $ Map.fromList [(e, showSoloPersonPracticeType e) 
| e <- [minBound..]]
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The error message is clear, but: 1. I do not know if this is even the correct approach and 2. If it is the correct approach, how do I put this last let result e = ... bit into a do block?

Alternatively, when I move the result function outside of the frontend function, I get this error:

frontend/src/Frontend.hs:177:17-41: error:
    • Could not deduce (Monad m0) arising from a do statement
      from the context: ObeliskWidget js t (R FrontendRoute) m
        bound by a type expected by the context:
                   forall js t (m :: * -> *).
                   ObeliskWidget js t (R FrontendRoute) m =>
                   RoutedT t (R FrontendRoute) m ()
        at frontend/src/Frontend.hs:(61,12)-(230,3)
      or from: a ~ ()
        bound by a pattern with constructor:
                   FrontendRoute_Main :: FrontendRoute (),
                 in a case alternative
        at frontend/src/Frontend.hs:174:9-26
      The type variable ‘m0’ is ambiguous
0

There are 0 answers