I have a simple function that reads a binary file one byte at a time. It get a compile time error, below. The problem seems to be that bs2, the resulting ByteString of BSSC.length, has an unknown type. Am I missing a type constraint on r?
import qualified Data.ByteString.Streaming.Char8 as BSSC
main :: IO ()
main = runResourceT $ dump $ BSSC.readFile "filename"
dump :: (MonadIO m) => BSSC.ByteString m r -> m ()
dump bs = do
len :> bs2 <- BSSC.length bs -- Data.Functor.Of (:>)
if len <= 1 then return ()
else dump $ BSSC.putStr $ BSSC.splitAt 1 bs2
Compile-time error:
Main.hs:166:46: error:
• Couldn't match expected type ‘BSSC.ByteString
(BSSC.ByteString m) r0’
with actual type ‘r’
‘r’ is a rigid type variable bound by
the type signature for:
dump :: forall (m :: * -> *) r.
MonadIO m =>
BSSC.ByteString m r -> m ()
at Main.hs:162:9
• In the second argument of ‘BSSC.splitAt’, namely ‘bs2’
In the second argument of ‘($)’, namely ‘BSSC.splitAt 1 bs2’
In the second argument of ‘($)’, namely
‘BSSC.putStr $ BSSC.splitAt 1 bs2’
• Relevant bindings include
bs2 :: r (bound at Main.hs:164:12)
bs :: BSSC.ByteString m r (bound at Main.hs:163:6)
dump :: BSSC.ByteString m r -> m () (bound at Main.hs:163:1)
The
ByteStringtype from streaming-bytestring has two type parameters. The first is the base monadmin which the values are produced (typicallyIO).The second is a special ending value
rthat is returned once theByteStringis exhausted. Usually it will be an uninformative(). However, it becomes very useful for defining functions likesplitAt :: Monad m => Int64 -> ByteString m r -> ByteString m (ByteString m r). The type means: "give me a limit position and a effectful stream of bytes that returns with anr, I will give you another stream that is no longer than the limit and returns with a effectful stream of bytes that returns with anr." This ending stream nested within the outer one can only be reached after the outer one is exhausted.lengthhas typeMonad m => ByteString m r -> m (Of Int r). It consumes the stream of values it receives as argument and returns an action in the base monad. TheByteStringexists no more. Thebs2that you pass tosplitAtis not aByteStringbut the ending value of the originalByteString, which has typer. And this causes a type error.