解决"没有...的实例。带导管的单向穿越

时间:2017-06-14 10:41:56

标签: haskell conduit

给出以下代码:

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的预期第二个参数?

1 个答案:

答案 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 bConduit text m binary,以便我们获得以下类型的等式:

a ~ text
b ~ binary

然后我们将结果应用于x,统一ConduitM b c m rConduitM 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 eConduitM a c m r统一起来。

a ~ d
c ~ Void
r ~ e

关注ad,我们有以下内容:

a ~ text
a ~ d
d ~ ByteString

因此text ~ ByteStringbinary ~ Text。现在请记住要使用encodeUtf8,我们需要Utf8 text binary约束,即Utf8 ByteString Text,这是错误的方法。