Composing streamly streams of different types

144 Views Asked by At

As per the streamly tutorial, it is possible to combine different streams using <> operator (re-exported from Semigroup by streamly) like this:

runStream $ ((readLn :: IO Int) |: nil) <> ((readLn :: IO Int) |: nil) & S.mapM print

However, I'd like to combine streams which have different types, but both work with print. Something like this:

runStream $ ((readLn :: IO Int) |: nil) <> ((readLn :: IO [Char]) |: nil) & S.mapM print

But this gives me an error:

<interactive>:27:45: error:
    • Couldn't match type ‘[Char]’ with ‘Int’
      Expected type: SerialT IO Int
        Actual type: SerialT IO [Char]
    • In the second argument of ‘(<>)’, namely
        ‘((readLn :: IO [Char]) |: nil)’
      In the first argument of ‘(&)’, namely
        ‘((readLn :: IO Int) |: nil) <> ((readLn :: IO [Char]) |: nil)’
      In the second argument of ‘($)’, namely
        ‘((readLn :: IO Int) |: nil) <> ((readLn :: IO [Char]) |: nil)
           & S.mapM print’

Any hints on how to do this?


The above code has been run in ghci with these are the imports:

import Streamly
import Streamly.Prelude ((|:), nil)
import qualified Streamly.Prelude as S
import Data.Function ((&))
1

There are 1 best solutions below

2
Daniel Wagner On

Since S.mapM only works on things that are already monads, presumably you can convert them to a shared type -- say, ones containing Strings -- then traverse the shared stream type. print is just putStrLn . show, so:

runStream $ (show <$> ((readLn :: IO Int) |: nil)) <> (show <$> ((readLn :: IO [Char]) |: nil)) & S.mapM putStrLn