2016-03-06 126 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