{-# LANGUAGE NoMonomorphismRestriction #-}
module Try where
f :: IO (a -> IO String)
f = return $ const getLine
main :: IO ()
main = do
g <- f
:: IO (a -> IO String)
g "String" >>= print
g 5 >>= print
即使使用NoMonomorphismRestriction
标志和显式类型签名,该模块也无法使用Couldn't match expected type ‘[Char]’ with actual type ‘Int’
进行编译,尽管g
是完全多态的。
答案 0 :(得分:5)
这不是单态限制的含义。单态限制表示如果一个定义没有类型签名并且左侧没有参数,它将专门用于单态类型(或者更确切地说只是单态以消除任何类约束)。您已提供类型签名,因此不适用。
这里的问题是你给了f
错误的类型。
f :: IO (a -> IO String)
实际上意味着
f :: forall a. IO (a -> IO String)
也就是说,首先选择一个类型a
,然后你可以绑定以获得a -> IO String
类型a
的单态函数。这个程序没有问题,例如:
main = do
g <- f
g "String" >>= print
g' <- f
g' 5 >>= print
但您的使用示例需要以下类型:
f :: IO (forall a. a -> IO String)
也就是说,您希望先绑定并稍后选择该类型,即使用多种类型的函数。这被称为“不可预测的类型”,不幸的是GHC在相当长的一段时间内并没有支持它们。据我所知。
解决此问题的方法是创建一个newtype
包装器,明确量化内部多态类型:
newtype R = R { getR :: forall a. a -> IO String }
f :: IO R
f = return $ R (const getLine)
main :: IO ()
main = do
g <- f
getR g "String" >>= print
getR g 5 >>= print