在 GHCi 中运行以下命令会在 上抛出错误,stuff' 4
但在 上不会抛出错误stuff 4
。为什么?
有办法修复吗?我想使用MkStuff'
而不是MkStuff
。
ghci>
:{
class MkStuff s m | m -> s where
stuff:: s -> m ()
instance MkStuff Int IO where
stuff = print
class MkStuff' s m | m -> s where
stuff' :: s -> m
instance MkStuff' Int (IO ()) where
stuff' = print
:}
ghci> stuff 4
4
ghci> stuff' 4
<interactive>:16:1: error: [GHC-39999]
• No instance for ‘MkStuff' Integer ()’ arising from a use of ‘it’
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
尽管我不完全确定,但我相信情况就是这样的。
GHCi 内部有一些神奇的功能。输入表达式后,GHCi 大致会尝试以下操作:
尝试推断
e :: IO a
一些a
。如果可能的话:a. 检查是否
a
是Show
类型。如果是,则运行操作e
,然后打印其类型的结果值a
(除非a~()
)。b. 否则,运行操作
e
然后打印其结果a
值。否则,尝试推断类的
e :: a
某些部分。如果可能,则打印获得的字符串。a
Show
show e
否则,打印类型错误。
在第一种情况下,当推断
stuff 4 :: IO a
GHCi 时可以看到stuff 4 :: m ()
,因此m ~ IO
。这可以用于提交到您的实例,并且一切都顺利进行。在第二种情况下,在推断
stuff' 4 :: IO a
GHCi 时可以看到stuff' 4 :: m
,因此m ~ IO a
。这不足以提交到实例,因为实例是关于IO ()
,并且a
尚未(尚未)推断为()
。如果存在另一个实例,instance MkStuff' Char (IO Bool) where ...
它可以提供另一个候选,因此我们无法提交。在步骤 1 中失败后,我们转到步骤 2,但
a
找不到具体内容。默认规则尝试a ~ ()
,因此出现奇怪的错误No instance for ‘MkStuff' Integer ()’
。唉,这个默认发生在流程中太晚了,无法提交到 IO 实例。尝试使实例头更加通用:
这正确地允许 GHCi 提交到实例。请注意,您将无法
IO
通过这种方式添加更多实例。