2016-03-06 97 views
2

考慮在Haskell以下兩個函數(我的實際代碼的最小示例):類型的呼叫

printSequence :: (Show a, Show b) => a -> b -> IO() 
printSequence x y = (putStr . show) x >> (putStr . show) y 

printSequence' :: (Show a, Show b) => a -> b -> IO() 
printSequence' x y = print' x >> print' y 
    where print' = putStr . show 

第一編譯好,但第二個產生錯誤:

Could not deduce (a ~ b) 
    from the context (Show a, Show b) 
     bound by the type signature for 
       printSequence' :: (Show a, Show b) => a -> b -> IO() 
     at test.hs:8:19-53 
     `a' is a rigid type variable bound by 
      the type signature for 
      printSequence' :: (Show a, Show b) => a -> b -> IO() 
      at test.hs:8:19 
     `b' is a rigid type variable bound by 
      the type signature for 
      printSequence' :: (Show a, Show b) => a -> b -> IO() 
      at test.hs:8:19 
    In the first argument of print', namely `y' 
    In the second argument of `(>>)', namely `(print' y)' 
    In the expression: (print' x) >> (print' y) 

我知道這個錯誤意味着GHC是需要xy等同類型。我不明白的是爲什麼。像print "fish" >> print 3.14這樣的語句在解釋器中工作得非常好,那麼爲什麼GHC抱怨xy是不同的類型,當我在兩個不同的時間調用我的print'函數?

+1

關於可怕的單態限制:http://stackoverflow.com/ question/32496864/what-is-the-monomorphism-restriction – chi

回答

1

添加一個明確的類型簽名:

printSequence' :: (Show a, Show b) => a -> b -> IO() 
printSequence' x y = print' x >> print' y 
    where 
    print' :: Show a => a -> IO() 
    print' = putStr . show 

或使用NoMonomorphismRestriction

{-# LANGUAGE NoMonomorphismRestriction #-} 

printSequence' :: (Show a, Show b) => a -> b -> IO() 
printSequence' x y = print' x >> print' y 
    where 
    print' = putStr . show 

然後,

\> printSequence' 5 "five" 
5"five" 
+0

這個在逐字複製時有效,但我有關於你的第一個解決方案的後續問題。爲什麼當我在同一行提供類型簽名時會失敗,比如'where print'=(putStr。show):: Show a => a - > IO()'? – ApproachingDarknessFish

+1

@ApproachingDarknessFish這是註釋=號右側的值,讓GHC推斷左側名稱的類型。 GHC爲沒有顯式函數參數的模式推斷單態類型,並且在右側聲明一個多態類型不會改變該規則。 – amalloy