2012-07-23 63 views
1

止損功能導致以下錯誤:我可以在IO monad中使用printf嗎?

Could not deduce (Text.Printf.PrintfType (m a0)) 
arising from the ambiguity check for `stopLoss' 
from the context (Monad m, 
       Text.Printf.PrintfType (m b), 
       Text.Printf.PrintfType (m a)) 
bound by the inferred type for `stopLoss': 
    (Monad m, Text.Printf.PrintfType (m b), 
    Text.Printf.PrintfType (m a)) => 
    Float -> Float -> Float -> m b 
Possible fix: 
    add an instance declaration for (Text.Printf.PrintfType (m a0)) 

When checking that `stopLoss' 
has the inferred type `forall (m :: * -> *) a b. 
    (Monad m, Text.Printf.PrintfType (m b), 
    Text.Printf.PrintfType (m a)) => 
    Float -> Float -> Float -> m b' 
Probable cause: the inferred type is ambiguous 

功能:

stopLoss qty pb lossRate = do 
    let t = qty * pb * (1 + sxf) 
    printf "Stop Loss at: %.2f\n" ((pb - (t * lossRate)/qty) :: Float) 
    printf "Lost Money: %.2f\n" ((t * lossRate) :: Float) 

任何建議表示讚賞!

+1

我建議爲'stopLoss'提供一個類型簽名。 'printf'的返回類型不限於'IO()',編譯器不能推斷它。 – Artyom 2012-07-23 03:00:16

+0

它通過添加類型簽名來解決。謝謝! – 2012-07-23 03:08:56

+0

另外,我真的推薦'printf'上的'formatting'。類型的自由度要少得多。 http://hackage.haskell.org/package/formatting-3.1.0 – 2014-02-14 11:38:34

回答

5

printf的類型是PrintfType r => String -> r。的PrintfType下列情況下可用:

IsChar c => PrintfType [c] 
PrintfType (IO a)  
(PrintfArg a, PrintfType r) => PrintfType (a -> r) 

(最後一個是隻是爲了讓printf的行爲一樣,如果它是polyvariadic。)

這裏stopLoss是一個多態函數;不能自動推斷出IO()類型,而GHC假設該函數適用於任何monad。所以,GHC抱怨說,對於通用monad而言,PrintfType的實例不存在。

提供類型簽名,如Float -> Float -> Float -> IO()應該有所幫助。

相關問題