给出以下代码:
import Data.Attoparsec.Text
import qualified Conduit as C
import qualified Data.Conduit.Combinators as CC
f :: FilePath -> FilePath -> IO ()
f infile outfile =
runResourceT $
CC.sourceFile infile $$ C.encodeUtf8C =$= x
其中x
的类型为ConduitM Text Void (ResourceT IO) ()
我的私有github存储库中出现以下编译时错误:
• No instance for (mono-traversable-1.0.2:Data.Sequences.Utf8
ByteString Text)
arising from a use of ‘C.encodeUtf8C’
• In the first argument of ‘(=$=)’, namely ‘C.encodeUtf8C’
In the second argument of ‘($$)’, namely ‘C.encodeUtf8C =$= x’
In the second argument of ‘($)’, namely
‘CC.sourceFile infile $$ C.encodeUtf8C =$= x’
如何解决此编译时错误?
修改
我对类型的理解:
> :t sourceFile
sourceFile
:: MonadResource m =>
FilePath
-> ConduitM
i bytestring-0.10.8.1:Data.ByteString.Internal.ByteString m ()
> :t ($$)
($$) :: Monad m => Source m a -> Sink a m b -> m b
> :t Conduit
type Conduit i (m :: * -> *) o = ConduitM i o m ()
> :i Source
type Source (m :: * -> *) o = ConduitM () o m ()
> :i Sink
type Sink i = ConduitM i Data.Void.Void :: (* -> *) -> * -> *
> :t (=$=)
(=$=)
:: Monad m => Conduit a m b -> ConduitM b c m r -> ConduitM a c m r
C.encodeUtf8C =$= x
归结为,我认为:
(mono-traversable-1.0.2:Data.Sequences.Utf8 text binary,
Monad m) =>
Conduit text m binary ()
=$=
ConduitM Text Void binary ()
产生返回类型
ConduitM text Void (ResourceT IO) ()
我认为这种类型,即C.encodeUtf8C =$= x
,并未统一到CC.sourceFile
的预期第二个参数?
答案 0 :(得分:2)
sourceFile
管道产生ByteString
,您需要解码到Text
x
才能使用。 编码指的是将Text
序列化为ByteString
以写入文件的相反方向。
使用decodeUtf8
。
-- Ignoring the `Monad` constraint.
(=$=) :: Conduit a m b -> ConduitM b c m r -> ConduitM a c m r
encodeUtf8 :: Utf8 text binary
=> Conduit text m binary
x :: ConduitM Text Void m ()
要将(=$=)
应用于encodeUtf8
,您必须统一Conduit a m b
和Conduit text m binary
,以便我们获得以下类型的等式:
a ~ text
b ~ binary
然后我们将结果应用于x
,统一ConduitM b c m r
和ConduitM Text Void m ()
:
b ~ Text
c ~ Void
到目前为止,编译器并没有抱怨,但由于涉及b
的两个等式,我们已经看到了不匹配:
b ~ binary
b ~ Text
在conduit-combinators
库中,类型变量binary
用于表示表示原始二进制数据的类型,通常为ByteString
,而不是像Text
这样的结构化数据。 }。
如果我们继续,结果的类型为ConduitM a c m r
,并且作为($$)
的第二个参数传递。
-- Expanding Source and Sink definitions, renaming type variables.
($$) :: Monad m => ConduitM () d m () -> ConduitM d Void m e -> m e
sourceFile infile
:: _ => ConduitM i ByteString m ()
使用source infile
作为第一个参数,我们将ConduitM () d m ()
与ConduitM i ByteString m ()
统一起来。
i ~ ()
d ~ ByteString
我们之前的encodeUtf8C =$= x
作为($$)
的第二个参数,我们将ConduitM d Void m e
与ConduitM a c m r
统一起来。
a ~ d
c ~ Void
r ~ e
关注a
和d
,我们有以下内容:
a ~ text
a ~ d
d ~ ByteString
因此text ~ ByteString
,binary ~ Text
。现在请记住要使用encodeUtf8
,我们需要Utf8 text binary
约束,即Utf8 ByteString Text
,这是错误的方法。