类型推断 - 无法推断出 Monad
Type inference - could not deduce Monad
我正在构建一种向用户显示对话框的方法。
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))
我想使用某种 'default' 实例来为 dialog
函数初始化 DialogConfig
,这样我就可以将它用作例如defaultConfig{_dialogConfig_content=content}
。但是,我正在与类型推断作斗争。这有效:
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
然而,当我使用一些默认值 DialogConfig
(例如这里直接内联它)时,它不会:
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
错误是:
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)
我可以使用 ScopedTypeVariables
并在 confirmDialog
中键入默认配置作为 DialogConfig t m a b
并且可以工作,但是即使没有它也不应该工作吗?在我看来,这些类型是相当明确的。
如评论中所述,问题是记录更新可以更改 记录的类型(起初可能会令人惊讶)。这是 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
因此,我们无法定义默认值:
> 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
的确,以上def
可以是任何类型。
一个可能的解决方案是通过要求 T a -> T a
延续函数来强制更新具有相同的类型。
> 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
以上d
是默认值,根据构造,更新后必须具有相同类型的记录。
有了镜头,可能会有更好的方法。
我正在构建一种向用户显示对话框的方法。
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))
我想使用某种 'default' 实例来为 dialog
函数初始化 DialogConfig
,这样我就可以将它用作例如defaultConfig{_dialogConfig_content=content}
。但是,我正在与类型推断作斗争。这有效:
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
然而,当我使用一些默认值 DialogConfig
(例如这里直接内联它)时,它不会:
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
错误是:
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)
我可以使用 ScopedTypeVariables
并在 confirmDialog
中键入默认配置作为 DialogConfig t m a b
并且可以工作,但是即使没有它也不应该工作吗?在我看来,这些类型是相当明确的。
如评论中所述,问题是记录更新可以更改 记录的类型(起初可能会令人惊讶)。这是 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
因此,我们无法定义默认值:
> 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
的确,以上def
可以是任何类型。
一个可能的解决方案是通过要求 T a -> T a
延续函数来强制更新具有相同的类型。
> 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
以上d
是默认值,根据构造,更新后必须具有相同类型的记录。
有了镜头,可能会有更好的方法。