代码之家  ›  专栏  ›  技术社区  ›  141592653

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

  •  2
  • 141592653  · 技术社区  · 6 月前

    在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
    
    1 回复  |  直到 6 月前
        1
  •  1
  •   chi    6 月前

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

    GHCi里面有一些魔力。输入表达式后,GHCi大致尝试以下操作:

    1. 试着推断 e :: IO a 对一些人来说 a .如果可能:

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

      b.否则,运行操作 e 然后打印其结果 价值。

    2. 否则,尝试推断 e :: a 对一些人来说 显示 。如果可能,打印通过以下方式获得的字符串 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 () ,以及 (尚未)推断为 () .如果另一个实例 instance MkStuff' Char (IO Bool) where ... 如果存在,它可以提供另一个候选人,所以我们不能承诺。

    如果第一步失败,我们转到第二步。但没有混凝土 可以找到。尝试默认规则 a ~ () 因此,你犯了一个奇怪的错误 No instance for ‘MkStuff' Integer ()’ 遗憾的是,这种违约发生得太晚,无法提交到IO实例。

    尝试使实例头更通用:

    instance a ~ () => MkStuff' Int (IO a) where
      stuff' = print
    

    这正确地允许GHCi提交到实例。请注意,您将无法添加涉及以下内容的其他实例 IO 以这种方式。