所以我简单地理解Rank2Types,但是当我尝试以下
时{-# LANGUAGE ImpredicativeTypes, RankNTypes #-}
import Data.Machine
f :: IO (Process a a)
f = return . auto $ id
GHC咳出来
Couldn't match type `MachineT m0 (Is a0) a0'
with `forall (m :: * -> *). Monad m => MachineT m (Is a) a'
Expected type: IO (Process a a)
Actual type: IO (MachineT m0 (Is a0) a0)
In the expression: return . auto $ id
In an equation for `f': f = return . auto $ id
Failed, modules loaded: none.
据我所知,GHC不允许我在Monad中加入一个咒语。是否存在原则性的量化逻辑原因,或者这仅仅是GHC的限制?或者我只是做些傻事?
答案 0 :(得分:9)
您可以按照以下方式使用您的特定示例:
{-# LANGUAGE ImpredicativeTypes, RankNTypes #-}
import Data.Machine
f = (return :: (forall a. Process a a) -> IO (forall a. Process a a)) (auto id)
正如Carl所说,你必须注意要盲目使用的功能,例如return
。即使在那时,在GHC中使用不可预测的类型也有些脆弱。我不推荐它。限制的原因很简单,在存在impredicative类型的情况下执行类型推断是很棘手的,另外,Haskell的表面语言没有适当的语法来指定你想要实例化的类型多态函数。
常见的解决方法是将内容包装在newtype
:
data PolyProcess = PP (forall a. Process a a)
f' :: IO PolyProcess
f' = return $ PP $ auto $ id