Khu*_*rya 11 haskell types coercion ghc
刚才我在 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]
Run Code Online (Sandbox Code Playgroud)
为什么f不是类型a -> [a]?我unsafeCoerce当然可以,但那又长又丑。
IO (a -> [a])是多态类型。展开,意思是forall a. IO (a -> [a])。现在,有两件事在这里不起作用。一,这是一个IO产生单态函数的多态动作。本质上,此操作的每次执行都会为一种类型生成一个函数。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 either line out and it will
Run Code Online (Sandbox Code Playgroud)
第二,GHC 不支持非谓词多态性。从理论上讲,如果你IO正确地编写了你的动作,你可以得到它IO (forall a. a -> [a]),但 GHC 不支持将多态类型(如forall a. a -> [a])放入容器中,如IO.
在您的情况下,由于您不使用f,GHC 不知道它应该在哪种类型上实例化操作,但它必须选择一个,因此默认为Any。
编辑:绕过“无不可预测类型”限制的传统方法是将它们隐藏到newtypes:
{-# LANGUAGE RankNTypes #-}
-- interestingly, this is a numeric type (it represents the natural numbers)
newtype Replicator = Replicator { runReplicator :: forall a. a -> [a] }
mkReplicator :: Int -> Replicator
mkReplicator i = Replicator (replicate i)
-- mkReplicator =# replicate
main = do
Replicator f <- mkReplicator <$> readLn
print (f (5 :: Int))
print (f (5 :: Float)) -- should work now
Run Code Online (Sandbox Code Playgroud)
可能不值得...