While I was exploring the library, I saw the following code.
look at unstreamChunks.
This code bundles the Stream of Char into chunks and returns it as Text. It creates and uses mutable arrays in the process.
What I think odd is the type signature of inner, which is inner :: MArray s -> Int -> s -> Int -> ST s Text. (Hover your mouse on inner and see the type signature if you want to).
So, (the type s representing the state of the MArray sand ST s Text) and (the type s representing the state in the Stream) are the same as "s". (The third argument type s is from Stream next s length.)
unstreamChunks uses runST. It means that s from the ST s Text, which is identical to s -> (s, Text), should cover RealWorld. Cause runST :: (forall s. ST s a) -> a and it consequently apply s -> (s, Text) to s = RealWorld.
However, s -> Step s Char in the Stream Char depends on concrete type [Char] in a specific application.
I'll show you an example below.
https://hackage.haskell.org/package/text-2.0.2/docs/src/Data.Text.Lazy.html#pack https://hackage.haskell.org/package/text-2.0.2/docs/src/Data.Text.Internal.Fusion.Common.html#streamList
pack = unstream . streamList . map safe.
s -> Step s Char from Stream Char is
next [] = Done
next (x : xs) = Yield x XS
It totally depends on concrete type [Char] and won't work for RealWorld, or it won't type check for runST.
I can't figure it out how it works!! But it works well.
So, I think that two different type parameter s from inner is not the same.
There's nothing to do with Stream Char and State s.
There's no code combining two different s type values.
The type signature of inner is even not an Haskell code. It's just a preview from hackage.
So, I concluded that hackage's auto generated type signature doesn't mutate original type parameter name even if it overlaps.
I want to get confirmation that my guess is correct.
Also, if I'm wrong and the two types are actually the same, I would appreciate it if you could explain why the code works well.