在我的库中,我想在文档中向用户公开底层monadic状态的名称,但我不希望它们能够拆开它 - 我想制作一个黑盒子。
因此,我开始使用以下类型别名完全使用代码:
type Surge e c z m = ErrorT (Failure z) (ReaderT (SurgeChan e c) (Parser' ByteString m))
然后,为了使其更加健壮,我将其更改为newtype
并启用了GeneralizedNewtypeDeriving
:
newtype Surge e c z m a = Surge
{ runSurge' :: ErrorT (Failure z) (ReaderT (SurgeChan e c) (Parser' ByteString m)) a }
deriving (Monad, Applicative, Functor)
我有一些其他代码需要像这样调整:
res <- flip St.evalStateT prod . flip runReaderT sc . runErrorT $ pipeline
==&GT;
res <- flip St.evalStateT prod . flip runReaderT sc . runErrorT . runSurge' $ pipeline
不幸的是,由于某种原因,在我进行type
- &gt; newtype
更改后,并非所有代码都会进行类型检查。这部分代码特别是:
{-# INLINE decodeAndHandlePacket #-}
decodeAndHandlePacket
= handlePacket ~< errorP (lift.lift.liftM (first DecodeFailure) . decodeGet $ decodePacket)
...现在没有出现相当长的错误,但之前没有:
src/Surge/Internal.hs:101:27:
Couldn't match type ‘ErrorT
(Failure z0) (t0 (St.StateT (Producer ByteString m0 x0) m0))’
with ‘Surge e c z m’
Expected type: Proxy a' a () p' (Surge e c z m) ByteString
Actual type: Proxy
a'
a
()
p'
(ErrorT
(Failure z0) (t0 (St.StateT (Producer ByteString m0 x0) m0)))
ByteString
Relevant bindings include
decodeAndHandlePacket :: Proxy a' a () p' (Surge e c z m) ()
(bound at src/Surge/Internal.hs:100:5)
handleCommand :: Handler c p' (Surge e c z m)
(bound at src/Surge/Internal.hs:84:7)
handleEvent :: Handler e p' (Surge e c z m)
(bound at src/Surge/Internal.hs:84:7)
handlePacket :: Handler ByteString p' (Surge e c z m)
(bound at src/Surge/Internal.hs:84:7)
stage :: Stage ByteString p' e c (Surge e c z m)
-> Producer ByteString (Surge e c z m) ()
(bound at src/Surge/Internal.hs:84:1)
In the second argument of ‘(~<)’, namely
‘errorP
(lift . lift . liftM (first DecodeFailure) . decodeGet
$ decodePacket)’
In the expression:
handlePacket
~<
errorP
(lift . lift . liftM (first DecodeFailure) . decodeGet
$ decodePacket)
我不知道该怎么做。双方看起来和我一模一样。
http://lpaste.net/109472提供完整代码。感谢。
答案 0 :(得分:3)
decodeAndHandlePacket
期望处理Surge e c z m
,但是你给它一个(ErrorT (Failure z0) (t0 (St.StateT (Producer ByteString m0 x0) m0)))
,即你没有用Surge
构造函数包装它。当您使用newtype包装器包装类型时,您必须确保在任何地方执行包装和解包。
答案 1 :(得分:1)
你想要
decodeAndHandlePacket
= handlePacket ~< hoist Surge (errorP (lift.lift.liftM (first DecodeFailure) . decodeGet $ decodePacket))
请注意,errorP
调用的返回类型为
Proxy a'0 a0 () p' (ErrorT (Failure ...)) ByteString
并且您想要用newtype替换第五个参数,即
Proxy a'0 a0 () p' (Surge e c z m) ByteString
此newtype是monad(类型构造函数),您需要将hoist
中的(ErrorT (Failure ...))
中的操作导入(Surge ...)
monad。