添加无关定义时,为什么在此程序中出现类型错误?

Ale*_*ing 12 haskell

Free当我遇到一个我并不理解的好奇的GHC行为时,我正在向同事展示.这是一个简单的,人为的程序,可以解决这个问题:

import Prelude hiding (readFile, writeFile)
import Control.Monad.Free
import Data.Functor.Sum

data FileSystemF a
  = ReadFile FilePath (String -> a)
  | WriteFile FilePath String a
  deriving (Functor)

data ConsoleF a
  = WriteLine String a
  deriving (Functor)

data CloudF a
  = GetStackInfo String (String -> a)
  deriving (Functor)

type App = Free (Sum FileSystemF (Sum ConsoleF CloudF))

readFile :: FilePath -> App String
readFile path = liftF (InL (ReadFile path id))

writeFile :: FilePath -> String -> App ()
writeFile path contents = liftF (InL (WriteFile path contents ()))
Run Code Online (Sandbox Code Playgroud)

我尝试添加另一个定义,但它不太正确:

writeLine :: String -> App ()
writeLine line = liftF (InR (WriteLine line ()))
Run Code Online (Sandbox Code Playgroud)

这里的问题是我错过了另一个InL.正确的定义应该是这样的:

writeLine :: String -> App ()
writeLine line = liftF (InR (InL (WriteLine line ())))
Run Code Online (Sandbox Code Playgroud)

但是,这不是重点.对我来说奇怪的是当我添加第一个不正确的定义时GHC产生的类型错误writeLine.具体来说,它产生了两种类型错误:

/private/tmp/free-sandbox/src/FreeSandbox.hs:26:27: error:
    • Couldn't match type ‘ConsoleF’ with ‘Sum ConsoleF CloudF’
        arising from a functional dependency between constraints:
          ‘MonadFree
             (Sum FileSystemF (Sum ConsoleF CloudF))
             (Free (Sum FileSystemF (Sum ConsoleF CloudF)))’
            arising from a use of ‘liftF’ at src/FreeSandbox.hs:26:27-66
          ‘MonadFree
             (Sum FileSystemF ConsoleF)
             (Free (Sum FileSystemF (Sum ConsoleF CloudF)))’
            arising from a use of ‘liftF’ at src/FreeSandbox.hs:29:18-48
    • In the expression: liftF (InL (WriteFile path contents ()))
      In an equation for ‘writeFile’:
          writeFile path contents = liftF (InL (WriteFile path contents ()))
   |
26 | writeFile path contents = liftF (InL (WriteFile path contents ()))
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

/private/tmp/free-sandbox/src/FreeSandbox.hs:29:18: error:
    • Couldn't match type ‘Sum ConsoleF CloudF’ with ‘ConsoleF’
        arising from a functional dependency between:
          constraint ‘MonadFree
                        (Sum FileSystemF ConsoleF)
                        (Free (Sum FileSystemF (Sum ConsoleF CloudF)))’
            arising from a use of ‘liftF’
          instance ‘MonadFree f (Free f)’ at <no location info>
    • In the expression: liftF (InR (WriteLine line ()))
      In an equation for ‘writeLine’:
          writeLine line = liftF (InR (WriteLine line ()))
   |
29 | writeLine line = liftF (InR (WriteLine line ()))
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

两个错误中的第二个(第29行的错误)是有道理的.这是我期望的错误.但第26行的错误完全让我感到困惑.定义writeFile是正确的!添加我不正确的定义writeLine应该没有任何影响writeFile,对吧?这是怎么回事?

我能够在GHC 8.0.2和GHC 8.2.1上重现这一点.我想知道这是GHC中的一个错误(所以我可以报告),或者我的代码是否是我不理解的问题.

dfe*_*uer 8

这是一个GHC错误.根据Ryan Scott的说法,修正了提交48daaaf0bba279b6e362ee5c632de69ed31ab65d(不要报告fundep想要/想要的错误).