Подтвердить что ты не робот

Почему я получаю ошибку типа в этой программе, когда добавляю несвязанное определение?

Я показывал коллегу Free, когда я сталкивался с любопытным поведением GHC, которого я действительно не понимаю. Вот простая, надуманная программа, которая typechecks:

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 ()))

Я попробовал добавить другое определение, но это было неверно:

writeLine :: String -> App ()
writeLine line = liftF (InR (WriteLine line ()))

Проблема в том, что мне не хватало другого InL. Правильное определение должно быть следующим:

writeLine :: String -> App ()
writeLine line = liftF (InR (InL (WriteLine line ())))

Однако это не так. Что странно для меня, это ошибка типа, которую 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 ()))
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Вторая из двух ошибок (одна в строке 29) имеет смысл. Его ошибка, которую я ожидал бы. Но ошибка на строке 26 меня полностью сбивает с толку. Определение writeFile верно! Добавление моего неправильного определения writeLine не должно влиять на writeFile, правильно? Что происходит?

Я смог воспроизвести это на GHC 8.0.2 и GHC 8.2.1. Id нравится знать, является ли это ошибкой в ​​GHC (так что я могу сообщить об этом), или если это проблема с моим кодом, который я не понимаю.

4b9b3361