3

これは理にかなっているように思えますが、タイプの問題があります。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にエンコードできますか?

4

1 に答える 1

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、存在量化のトリックを使用する代わりに、実際には s のリストを送信することをお勧めしますが、興味がある場合に備えて、それがどのように行われるかを示すためだけに含めました.

于 2013-07-07T02:52:07.660 に答える