这似乎是一个合理的想法,但我遇到类型麻烦。我希望有一个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
函数来将它们显示给用户。我希望能够改变一个,只要列表和功能匹配。
这样的事情可能吗?也许我想要的约束可以以某种方式编码成GADT?
答案 0 :(得分:4)
你不能按照你提出的方式做到这一点,但是你可以稍微欺骗并获得几乎同样好的东西:
{-# 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
的列表,而不是使用存在量化技巧,但我把它包括在内只是为了表明如果你好奇的话会怎么做。