I am building a way to display a dialog to users.
data DialogConfig t m b e =
DialogConfig { _dialogConfig_title :: Dynamic t T.Text
, _dialogConfig_content :: b -> m (Dynamic t (Maybe b))
, _dialogConfig_footer :: Dynamic t (Maybe b) -> m (Event t e)
}
dialog :: MonadWidget t m =>
DialogConfig t m b e -> Event t b -> m (Event t (DialogEvent e))
I would like to use some kind of 'default' instance to initialize DialogConfig
for the dialog
function, so that I could use it as e.g. defaultConfig{_dialogConfig_content=content}
. However, I'm fighting with type inferrence. This works:
confirmDialog :: forall t m. MonadWidget t m =>
T.Text -> Event t T.Text -> m (Event t ())
...
evt <- dialog
(DialogConfig { _dialogConfig_title = constDyn title
, _dialogConfig_content = content
, _dialogConfig_footer = buttons}
) contentEvt
However, when I use some default DialogConfig
(e.g. here directly inlining it), it doesn't:
evt <- dialog
(DialogConfig { _dialogConfig_title = constDyn mempty
, _dialogConfig_content = const $ return $ constDyn Nothing
, _dialogConfig_footer = const $ return never }
{ _dialogConfig_title = constDyn title
, _dialogConfig_content = content
, _dialogConfig_footer = buttons}
) contentEvt
The errors are:
Could not deduce (Reflex t0) arising from a use of ‘constDyn’ from the context (MonadWidget t m)
Could not deduce (Monad t1) arising from a use of ‘return’ from the context (MonadWidget t m)
I can use ScopedTypeVariables
and type the default config in the confirmDialog
as DialogConfig t m a b
and that works, however shouldn't it work even without it? It seems to me that the types are rather unambiguous.
As mentioned in the comments, the problem is that record update can change the type of the record (which can be surprising at first). Here's a test in GHCi:
> data T a = T { tA :: a }
> let x = T "foo"
> :t x
x :: T [Char]
> :t x { tA = True }
x { tA = True } :: T Bool
So, we can't define a default:
> let def :: Read a => T a ; def = T (read "True")
> :t def :: T Bool
def :: T Bool :: T Bool
> :t def { tA = 5 }
Could not deduce (Read t0) arising from a use of ‘def’
The type variable ‘t0’ is ambiguous
Indeed, above def
could be of any type.
A possible solution could be forcing the update to have the same type by requiring a T a -> T a
continuation function.
> let defF :: Read a => (T a -> T a) -> T a ; defF f = f (T (read "True"))
> :t defF (\d -> d { tA = False })
defF (\d -> d { tA = False }) :: T Bool
Above d
is the default which, by construction, must have the same type of the record after the update.
With lenses, there might be better approaches.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With