了解流媒体库中的类型

Understanding types in the streaming libarary

关于 streamingStream (Of a) m r 中的 m 是什么?我怎么能从文档中弄清楚这一点 (抱歉,这里是菜鸟)?

我想了解该类型的含义,以便我可以在使用 servant 创建请求流并尝试像这样使用它时解决我的具体问题:

post :: Maybe Int -> ClientM [BlogPost]
post = ...

stream :: Stream (Of (ClientM [BlogPost])) ClientM ()
stream = S.map posts $ S.each $ [Just p | p <- [1..5]]

main = do
  let url = ...
  S.print $ S.map (\x -> runClientM x url) stream

但我收到以下错误:

• Couldn't match type ‘ClientM’ with ‘IO’
  Expected type: S.Stream (S.Of (ClientM [BlogPost])) IO ()
    Actual type: S.Stream (S.Of (ClientM [BlogPost])) ClientM ()

如果单独给出,Stream (Of a) m r 中的 m 可以是任何类型。

考虑模块中的特定功能时,请注意类型约束。例如,yield 函数具有以下类型:

yield :: Monad m => a -> Stream (Of a) m ()

这里,m 被限制为 Monad 实例的任何类型。这可能是 IO[](列表)、MaybeStateReader

另一个函数具有这种类型:

stdinLn :: MonadIO m => Stream (Of String) m ()

这里,m 被限制为 MonadIO 实例的任何类型。 MonadIO 类型 class 是 Monad 的子 class,在某种意义上,要使类型成为 MonadIO,它必须已经是 Monad.

AFAICT,IO 也是 MonadIO,但是例如Maybe 不是。

因此,模块中的某些功能比其他功能受到更多限制。 yield 函数比 stdinLn 函数受到的限制更少。您可以将 Maybe 作为 myield 一起使用,但不能与 stdinLn.

一起使用

关于您的具体问题,OP 中没有足够的信息进行重现,但看起来 main 使用了 Streaming.Prelude 中的 map 函数:

map :: Monad m => (a -> b) -> Stream (Of a) m r -> Stream (Of b) m r

此处,m 必须是 Monad 实例。在 Haskell 中,main 函数必须具有类型 IO (),因此当使用 do 表示法时,Monad 实例被推断为 IO .错误消息表明编译器期望 mIO.