2017-08-10 15 views
1

次のコードは、「C1」をコンパイルしタイプファミリーをjsonに格納した後でそれを検証する方法は?

の誤差は「C」とタイプ「C1」を 一致しませんでし与えないであろうコンストラクタと パターンによって結合剛性型変数であり: SomeReq :: forall c。コネティカットC =>必須のC - > SomeReq、 式の「RUN」

{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE ExistentialQuantification #-} 

module Main where 

import qualified Data.Text as T 

class Conn c where 
    data Auth c :: * 
    data Env c :: * 
    data Req c :: * 

    getEnv :: Auth c -> IO (Env c) 
    runReq :: Env c -> Req c -> IO String 

data SomeAuth = forall c. (Conn c) => SomeAuth (Auth c) 
data SomeReq = forall c. (Conn c) => SomeReq (Auth c) 

run :: SomeAuth -> SomeReq -> IO String 
run (SomeAuth auth) (SomeReq req) = do 
    env <- getEnv auth 
    runReq env req 

main :: IO() 
main = return() 

ためexistentialsの理由は、私は、JSONでこれらのデータ型を格納する必要があるということです。 (Auth c)(Req c)は常に別々に格納されますが、常に一緒に使用されます。

この作業を行う唯一の方法は、これらのタイプが一致するかどうかを検証するために何らかのランタイムチェックを行うことです。私はそれをどうやって行うのか分からない。

+0

あなたのJSONストレージは 'c 'が何であるかを判断していますか?あるいは 'c'はコードの静的構造によって決まりますか? –

+0

'c'はリクエストを実行できるサービスです。例えばS3、またはGoogle – whitehead1415

答えて

2

SomeAuthSomeReqを指定すると、ラップするタイプが同じかどうかを調べる方法がありません。有限多くの可能性(有限「宇宙」)がある場合は、それらをタグ付けするためにGADTを使用することができます。

data CTag c where 
    C1T :: CTag C1 
    C2T :: CTag C2 
    ... 

SomeReqとパターンマッチングでCTagSomeAuthにし、1を貼り付けます。

cは、古いものになることができれば、あなたの最善の策はSomeAuthSomeReqコンストラクタにTypeable制約を追加、Data.Typeableを使用することです。それらを両方開くと、タイプが一致するかどうかを調べることができます。一致する場合は、そのタイプの証拠が得られます。

+0

その簡単な解決法をお寄せいただきありがとうございます。 SomeAuthを構築する汎用関数を持つことは可能ですか? 'mkSomeAuth :: Auth c - > SomeAuth'のようなもの – whitehead1415

+0

もっと具体的にはSomeAuthでCTagsを追加するつもりですので、'(Auth c) - > CTag c'からどうやって行くのでしょうか? – whitehead1415

+0

私は戻ってきました制約として 'Typable'を追加して遊んでみると少し迷っています。あなたは例を指摘できますか? – whitehead1415

関連する問題