2012-07-23 61 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()应该有所帮助。

相关问题