{-# 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进行编译。

最佳答案

这不是单态限制的含义。单态性限制表示,如果定义没有类型签名并且左侧没有参数,则它将专用于单态类型(或者说是足以消除任何类约束的单态性)。您已提供类型签名,因此它不适用。

这里的问题是您为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

关于haskell - 模式绑定(bind)中的单态性限制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26400980/

10-11 23:50