Как решить: не удалось сопоставить тип "o" с "элементом mono0"?

При вставке следующего кода из stm-pipeline:

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)

У меня такое ощущение, что я уже сталкивался с подобными проблемами раньше, но я не сразу понимаю, что вызывает конфликт.

1 ответ

Я не уверен во всех деталях, но похоже, что GHC не смог полностью определить тип... но, к счастью, явно аннотируя тип gather помогло:

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

Мне также пришлось использовать явный forall для правильной привязки переменных типа в gather:

mygatherFrom :: forall m o.  ...
Другие вопросы по тегам