2013-07-06 4 views
3

이것은 합리적인 것 같지만 유형 문제가 있습니다. Server에 옵션 목록을 보낼 수있는 Client을 갖고 싶습니다. 그러면 하나를 선택하고 선택한 요소를 반환합니다. 이 같은 일이 :동적 요청/응답 유형의 파이프?

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에 인코딩 할 수 있을까요?

+2

요청으로 서버가 무엇을합니까? 어떤 유형을 얻을지 모르는 경우 어떻게 할 수 있습니까? 해당 형식을 String으로 변환 할 수있는 경우 (함수를 사용하여), 첫 번째 경우에는 String을 전달하지 않는 이유는 무엇입니까? – bennofs

+0

나는 그것이 사실이라고 생각한다. 문자열에서 응답을 다시 변환하지 않아도 좋지만 큰 문제는 아닙니다. – ajp

+2

@ajp : (a) 클라이언트가 인터페이스 (* '*'예 : * '보기')를 준수하는 * * 유형의 값을 보냅니다. (b) 서버는 * any * 유형의 값을 허용합니다. (c) 클라이언트가 서버로부터 응답을 받으면 어떤 유형의 메시지인지를 알 수 있습니까? 단계 (c)가 고착 지점이 될 것입니다 (서버가 동일한 값으로 응답하기로 결정하거나 전혀 응답하지 않는 경우 어떻게되는지 고려하십시오). 당신은 아마도 합계 타입이나'Typeable' /'Dynamic' 같은 것을 원할 것입니다. 존재 유형 (GADT로 얻는 것)은 원래 유형이 무엇인지 알기 위해 압축을 풀 수 없습니다. –

답변

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의 목록을 전송하는 것이 좋지만, 궁금한 점을 대비하여 그 방법을 보여주기 위해 포함 시켰습니다.

+0

감사합니다! 나는 실제로''Int''에'[String]'을 가지고갔습니다. – ajp

관련 문제