这似乎是一个合理的需求,但我遇到了类型问题。我想要一个 Client
可以将选项列表发送到 Server
,后者将选择一个并返回所选元素。所以像这样:
module Toy where
import Pipes
asker :: Monad m => () -> Client ([a], a -> String) a m ()
asker () = do
_ <- request ([0.0, 2.0], show)
_ <- request (["3", "4"], show)
return ()
这个想法是服务器可以在列表的每个元素上调用a -> String
函数来将它们显示给用户。我希望能够改变 a,只要列表和函数匹配。
这样的事情可能吗?也许我想要的约束可以以某种方式编码到 GADT 中?
最佳答案
你不能完全按照你的要求去做,但你可以稍微作弊并得到几乎一样好的东西:
{-# LANGUAGE ExistentialQuantification #-}
module Toy where
import Control.Monad
import Pipes
import Pipes.Prelude (foreverK)
data Request = forall a . Request [a] (a -> String)
asker :: Monad m => () -> Client Request Int m ()
asker () = do
_ <- request (Request [0.0, 2.0] show)
_ <- request (Request ["3", "4"] show)
return ()
server :: Request -> Server Request Int IO r
server = foreverK $ \req -> case req of
Request as f -> do
choice <- lift $ do
let select = do
putStrLn "Select an option"
forM_ (zip [0..] as) $ \(n, a) ->
putStrLn $ show n ++ ": " ++ f a
n <- readLn
if (n >= length as)
then do
putStrLn "Invalid selection"
select
else return n
select
respond choice
不是返回所选的值,而是返回一个与所选元素的索引对应的 Int
。剩下的只是使用 ExistentialQuantification
。
像其他人推荐的那样,我建议您实际上只发送一个 String
列表,而不是使用存在量化技巧,但我包含它只是为了展示如何做到这一点,以防万一很好奇。
关于haskell - 具有动态请求/响应类型的管道?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17507802/