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.
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
gatherhelped:I also had to use an explicit forall to properly bind the type variables in gather: