2

任何人都知道我该如何处理因使用“从不”而引起的“无法推断(反射 t0)”之类的错误?

我正在重构应用程序的一部分,这意味着一些never事件不会被使用,但由于它们是never开始的,所以我不在乎。

我也可以让 GHC 不在乎吗?

我知道-XExtendedDefaultRules哪个可能至少有助于将类型从forall t a. Event t aforall t. Event t ()

而且我也想专门研究tGHC 接受的任何值,因为它无论如何都会导致死代码。

我可以在default (...)声明中写一些有用的东西吗?还是同样不可能编写default (IO)将非完全指定的 monad 专门用于 IO?

编辑:在#reflex-frp @dalaing 上要求提供代码示例,这就是我为他整理的内容:https ://gist.github.com/Wizek/d14aada2d75637cb4f424f8a324c7ad7

第 1 节和第 2 节编译,第 3 节不编译。但我也想让 3 编译,因为编译器抱怨只能是死代码的歧义。

4

2 回答 2

3

与#reflex-frp 上的@dalaing 一起,我们发现never :: Event t ()如果-XScopedTypeVariables启用并且父小部件具有forall t. Reflex t =>约束或类似条件,则该方法有效。

例如,链接代码示例中的第 3 节可以这样修改:

{-# language ScopedTypeVariables #-}

main = run 3000 $ mainWidget foo

foo :: forall t m. MonadWidget t m => m ()
foo = do
  let buttonEv = never :: Event t ()
  buttonEv <- button "click me"
  clicksCountDy <- count buttonEv
  display clicksCountDy

哪个编译。但是必须在任何地方指定事件类型很不方便,而且它也可能不像我们想要的那样 DRY,所以 -XPartialTypeSignatures 可以通过never :: Event t _

甚至更好,我发现,我们可以这样never @t-XTypeApplications

{-# language ScopedTypeVariables #-}
{-# language TypeApplications #-}

main = run 3000 $ mainWidget foo

foo :: forall t m. MonadWidget t m => m ()
foo = do
  let buttonEv = never @t
  buttonEv <- button "click me"
  clicksCountDy <- count buttonEv
  display clicksCountDy

所以从现在开始,我可能会制定一个政策,在我的反射相关代码部分我从不写never,总是写(never @t),这在很大程度上完美地解决了这个问题。

我只是仍然希望 GHC 可以被要求在一般情况下对死代码进行更宽松的类型检查,不仅仅是在反射方面,但现在这可能是不可能的。

于 2019-02-13T07:55:22.000 回答
0

使用

foo :: forall t m. MonadWidget t m => m ()
foo = do
  let buttonEv = never @t
  buttonEv <- button "click me"
  clicksCountDy <- count buttonEv
  display clicksCountDy

这里真的不是问题never。这是一个不将动作绑定到当前单子的问题。有问题的行可能是任何东西:

let buttonEv = button "never click me"

这将创建一个按钮小部件操作,但绝不会将其“连接”到当前小部件。您不会在应用程序中看到“从不点击我”按钮。

另一方面,如果您将never事件连接到您的小部件,

buttonEv <- return never

您将不再需要@t注释。

但最终,我发现--注释在死代码的实例中效果很好。

-- let buttonEv = never

如果必须,请保留代码,但这是告诉编译器代码不重要的最佳方式。

于 2019-02-13T13:35:55.020 回答