Can you substitute Duplex for Readable when using streams?

#1

Hi, I’m new to PureScript and I’m trying to make a function that takes a file path and returns a readline interface. The stream passed into RL.createInterface is a normal readable stream or a gunzip’ed readable stream depending on the extension of the file. But this doesn’t compile:

createInterface :: String -> Effect RL.Interface
createInterface path = do
  stream' <- stream
  RL.createInterface stream' mempty
  where stream = case (path # endsWith ".gz") of
                  false -> createReadStream path
                  true -> do
                    rs <- createReadStream path
                    gz <- createGunzip
                    _ <- rs `pipe` gz
                    pure gz

I know that createReadStream returns Effect Readable (), and here createGunzip returns Effect Duplex. How can this be made to work? Looking at the docs for Duplex, it seems that it can be treated as Readable.

By the way, refactoring the function into this form allows it to work:

createInterface :: String -> Effect RL.Interface
createInterface path = do
  rs <- createReadStream path
  case path # endsWith ".gz" of
    false -> RL.createInterface rs mempty
    true -> do
      gz <- createGunzip
      _ <- rs `pipe` gz
      RL.createInterface gz mempty

But I’m still curious about why my original version doesn’t work.

#2

The capabilities in the API are structural types, so the subtyping only works when passing them to consumers that are appropriately polymorphic. It works the same as records:

getFoo :: forall r. { foo :: String | r } -> String

This function is polymorphic over the input record, so I can pass in various shapes and they will all typecheck. However, that does not mean that any shape I can pass to this function is interchangeable in general.

makeFoo bool = if bool then { foo: "foo" } else { foo: "foo", bar: 42 }

Both of these shapes could be given to getFoo, but this will not type check because branches must all return the same type, and these are distinct types.