haskell - 具有动态请求/响应类型的管道?

标签 haskell polymorphism gadt haskell-pipes

这似乎是一个合理的需求,但我遇到了类型问题。我想要一个 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/

相关文章:

haskell - 如何在 Haskell 中为 GADT 派生数据实例?

haskell - 没有因使用 `X' 而产生的 (Show a) 实例

haskell - 在 readFile 后使用行

haskell - Haskell 类型类 'Real' 是用词不当吗?

C++ - vector<> 中的 std::unique_ptr 是 nullptr

java - 如何访问子类中的获取和设置?

c++ - 如何更改唯一指针 vector 的可见性

haskell - 弱化 GADT 类型约束以处理不可预测的数据

opengl - Haskell GLUT 库中的 ($=)(美元等于)运算符有什么作用?

data-structures - 如何在 Haskell 中实现半边数据结构?