How to resolve: Couldn't match type ‘o’ with ‘Element mono0?

81 Views Asked by At

When pasting the following code from 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

I get the error:

    • 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)

My imports and language extensions are as follows:



{-# 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)

I get the sense I've seen this sort of issue before, but I'm not immediately sure what is causing the conflict.

1

There are 1 best solutions below

0
bbarker On

I'm not certain of all the details, but it seems like GHC wasn't able to fully infer the type ... but happily, explicitly annotating the type of gather helped:

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

I also had to use an explicit forall to properly bind the type variables in gather:

mygatherFrom :: forall m o.  ...