我刚才在Haskell进行一些代码高尔夫球运动,当时我遇到了一个对我来说没有太大意义的错误。决定在GHCi中进行检查,现在我真的很困惑。
λ> :t replicate <$> readLn
replicate <$> readLn :: IO (a -> [a])
λ> f <- replicate <$> readLn
-- I type 4 and press Enter
λ> :t f
f :: GHC.Types.Any -> [GHC.Types.Any]
为什么f
不是a -> [a]
类型?我当然可以unsafeCoerce
,但这又冗长又丑陋。
IO (a -> [a])
是多态类型。展开,表示forall a. IO (a -> [a])
。现在,有两件事在这里不起作用。第一,这是一个产生单态函数的多态IO
操作。本质上,每次执行此操作都会为one类型产生一个函数。 a -> [a]
并不是真正有效的类型,但是如果您想使用forall a. a -> [a]
,就不会得到一个:
main = do
f <- replicate <$> readLn
print (f (5 :: Int)) -- f can be *one of* Int -> [Int] or Float -> [Float], but not both
print (f (5 :: Float)) -- doesn't compile, comment this line out and it will
[二,GHC不支持强制性多态性。从理论上讲,如果您正确地编写了IO
操作,则可以将其设为IO (forall a. a -> [a])
,但是GHC不支持将多态类型(例如forall a. a -> [a]
)放入容器中,例如IO
。
在您的情况下,由于您不使用f
,因此GHC不知道应以哪种类型实例化操作,但是它必须选择一个,因此默认为Any
。