在 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 ...
,它可以提供另一个候选者,所以我们不能提交。
尝试使实例头更通用:
instance a ~ () => MkStuff' Int (IO a) where
stuff' = print