GADTs打破了Haskell的等式推理吗
我有下面的解释器,它使用操作包中的ProgramTGADTs打破了Haskell的等式推理吗,haskell,gadt,Haskell,Gadt,我有下面的解释器,它使用操作包中的ProgramT {-# LANGUAGE GADTs #-} import Control.Monad ((<=<)) import Control.Monad.Operational data Motor' a where --Define GADT serialNewportT :: (Monad m, MonadIO m) => ProgramT Motor' m a -> m a serialNewportT = eva
{-# LANGUAGE GADTs #-}
import Control.Monad ((<=<))
import Control.Monad.Operational
data Motor' a where
--Define GADT
serialNewportT :: (Monad m, MonadIO m) => ProgramT Motor' m a -> m a
serialNewportT = eval <=< viewT
where
eval :: (Monad m, MonadIO m) => ProgramViewT Motor' m v -> m v
eval (Return x) = return x
eval (x :>>= k) = f x >>= serialNewportT . k
f :: (Monad m, MonadIO m) => Motor' a -> m a
f = undefined -- excluded for brevity
但是,此代码失败并显示错误消息
Couldn't match type ‘b’ with ‘c’
‘b’ is a rigid type variable bound by
a pattern with constructor
:>>= :: forall (instr :: * -> *) (m :: * -> *) a b.
instr b -> (b -> ProgramT instr m a) -> ProgramViewT instr m a,
in an equation for ‘eval’
‘c’ is a rigid type variable bound by
the type signature for
serialNewportT :: (Monad m, MonadIO m) =>
(Motor' c -> m c) -> ProgramT Motor' m a -> m a
Expected type: Motor' c
Actual type: Motor' b
由于我只是将全局名称替换为同一类型的本地名称,我会认为它应该能够顺利工作。如何将类型作为参数与
f
统一?您没有正确翻译f的类型。在原始代码中,f
的类型为所有a的。(..)=>电机'a->MA
。对于任何a
,它都可以用类型Motor'a
实例化,但在非工作代码中,您声明它的类型与programmat Motor'ma
中的类型完全相同,而在函数体中,您对aMotor'b
调用f
(存在量化)键入b
您只需要更高级别的类型:
serialNewportT :: (Monad m, MonadIO m) => (forall x . Motor' x -> m x) -> ProgramT Motor' m a -> m a
您没有正确翻译
f
的类型。在原始代码中,对于任何a
,它可以用类型Motor'a
实例化,但在非工作代码中,您声明它的类型与ProgramT Motor'ma
中的类型完全相同,而在函数体中,您对Motor'b
调用f
(存在量化)类型b
。您可能只需要更高级别的类型:serialnewport::(Monad m,MonadIO m)=>(对于所有x.Motor'x->mx)->ProgramT Motor'm a->m a
@user2407038似乎是对meUgh的一个回答。我对作用域类型变量做了大量研究,试图使所有变量都匹配,但没有研究排名N的类型。我想是时候学习它们了。@user2407038,如果你想回答这个问题,我会给你学分。
serialNewportT :: (Monad m, MonadIO m) => (forall x . Motor' x -> m x) -> ProgramT Motor' m a -> m a