0

stm-conduit粘贴以下代码时:

mygatherFrom :: (MonadIO m, MonadUnliftIO m)
           => Int                -- ^ Size of the queue to create
           -> (TBQueue o -> m ()) -- ^ Action that generates output values
           -> ConduitT () o m ()
mygatherFrom size scatter = do
    chan   <- liftIO $ newTBQueueIO (fromIntegral size)
    worker <- lift $ async (scatter chan)
    gather worker chan
  where
    gather worker chan = do
        (xs, mres) <- liftIO $ atomically $ do
            xs <- whileM (not <$> isEmptyTBQueue chan) (readTBQueue chan)
            (xs,) <$> pollSTM worker
        traverse_ yield xs
        case mres of
            Just (Left e)  -> liftIO $ throwIO (e :: SomeException)
            Just (Right r) -> return r
            Nothing        -> gather worker chan

我得到错误:

    • Couldn't match type ‘o’ with ‘Element mono0’
      ‘o’ is a rigid type variable bound by
        the type signature for:
          mygatherFrom :: forall (m :: * -> *) o.
                          (MonadIO m, MonadUnliftIO m) =>
                          Int -> (TBQueue o -> m ()) -> ConduitT () o m ()
        at app/Main.hs:(273,1)-(276,32)
      Expected type: ConduitT () o m ()
        Actual type: ConduitT () (Element mono0) m ()
    • In a stmt of a 'do' block: gather worker chan
      In the expression:
        do chan <- liftIO $ newTBQueueIO (fromIntegral size)
           worker <- lift $ async (scatter chan)
           gather worker chan
      In an equation for ‘mygatherFrom’:
          mygatherFrom size scatter
            = do chan <- liftIO $ newTBQueueIO (fromIntegral size)
                 worker <- lift $ async (scatter chan)
                 gather worker chan
            where
                gather worker chan
                  = do (xs, mres) <- liftIO $ atomically $ ...
                       ....
    • Relevant bindings include
        chan :: TBQueue o (bound at app/Main.hs:278:5)
        scatter :: TBQueue o -> m () (bound at app/Main.hs:277:19)
        mygatherFrom :: Int -> (TBQueue o -> m ()) -> ConduitT () o m ()
          (bound at app/Main.hs:277:1)

我的导入和语言扩展如下:



{-# LANGUAGE RankNTypes                  #-}
{-# LANGUAGE ScopedTypeVariables         #-}

{-# LANGUAGE LambdaCase         #-}

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE AllowAmbiguousTypes #-}

module Main where

import           ClassyPrelude                    hiding (hClose)
import           Conduit
import           Control.Concurrent.STM.TBQueue   (TBQueue, writeTBQueue)
import qualified Control.Exception.Safe           as Ex
import           Control.Monad.Catch              (MonadMask)
import           Control.Monad.Writer
import           Data.Bits                        (shiftR, (.&.))
import qualified Data.ByteString.Char8            as B
import           Data.Conduit.Async
import qualified Data.Conduit.List                as CL
import           Data.Function                    ((&))
import qualified Data.List as List
import qualified Data.Text                        as T
import           GHC.IO.Handle                    (Handle, hClose)
import qualified Network.Simple.TCP               as TCP
import qualified Network.Socket                   as NS
import qualified System.IO                        as IO
import           UnliftIO.Concurrent              (ThreadId, forkIO, threadDelay)

我觉得我以前见过这类问题,但我不确定是什么导致了冲突。

4

1 回答 1

2

我不确定所有细节,但似乎 GHC 无法完全推断出类型......但很高兴,明确地注释了gather帮助的类型:

gather :: Async b -> TBQueue o -> ConduitT i o m b

我还必须使用显式的 forall 来正确绑定收集中的类型变量:

mygatherFrom :: forall m o.  ...
于 2020-07-16T21:02:29.363 回答