2017-10-05 30 views
12

當我遇到奇怪的GHC行爲時,我並沒有真正理解,當時我正在展示一位同事Free。下面是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()))) 

但是,這不是重點。對我來說奇怪的是,當我添加第一個不正確的writeLine的定義時,GHC產生的類型錯誤。具體而言,它產生類型錯誤:

/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上重現這一點。我想知道這是否是GHC中的錯誤(所以我可以報告它),或者如果這是我的代碼的問題,我不明白。

+6

哦,這是一個偉大的。注意,如果你把錯誤的'writeLine'定義放在其他定義之後,那麼可疑的錯誤就會消失。 :) – Alec

+4

我已打開[GHC Trac#14327](https://ghc.haskell.org/trac/ghc/ticket/14327)來跟蹤此問題。 –

+0

這個問題似乎與FD有關,因爲專門研究'liftF':: Functor f => f a - > Free f a'擺脫了額外的錯誤。也許我錯過了一些東西。 – Alec

回答

相關問題