解决 "No instance for ..." 与导管的单遍历
Resolving "No instance for ..." with conduit's mono-traversable
给定以下代码:
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 ()
产生return类型的
ConduitM text Void (ResourceT IO) ()
而且我假设这种类型,即 C.encodeUtf8C =$= x
,不统一到 CC.sourceFile
的预期第二个参数?
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
,这是错误的方法。
给定以下代码:
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 ()
产生return类型的
ConduitM text Void (ResourceT IO) ()
而且我假设这种类型,即 C.encodeUtf8C =$= x
,不统一到 CC.sourceFile
的预期第二个参数?
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
,这是错误的方法。