GHCi 未推断某些 IO 操作的实例

问题描述 投票:0回答:1

在 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
haskell ghci
1个回答
0
投票

虽然我不完全确定,但我相信这就是发生的事情。

GHCi 内部有一些魔力。输入表达式后,GHCi 会尝试执行以下操作:

  1. 尝试推断

    e :: IO a
    一些
    a
    。如果可以的话:

    a.检查

    a
    是否为
    Show
    类型。如果是这样,请运行操作
    e
    ,然后打印其类型为
    a
    的结果值(除非
    a~()
    )。

    b.否则,运行操作

    e
    ,然后打印其结果
    a
    值。

  2. 否则,请尝试推断

    e :: a
    a
    的某些
    Show
    。如果可能的话,打印
    show e
    得到的字符串。

  3. 否则,打印类型错误。

在第一种情况下,当推断

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
© www.soinside.com 2019 - 2024. All rights reserved.