2017-08-10 45 views
1

下面的代碼不會編譯並給出的誤差如何驗證類型家庭存儲在json後?

無法與「C」 「C1」匹配類型「C1」是 結合的圖案構造的剛性類型的變量: SomeReq :: forall c。康涅狄格州C =>所需物品Ç - > SomeReq, 爲「運行」

{-# 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)總是seperatly存儲,但總是一起使用。

我假設的唯一可能的方法,使這項工作是有某種運行時檢查,以驗證這些類型匹配。我不知道該怎麼做。

+0

你是說,你的JSON存儲決定了'C'是什麼?或者''是由代碼的靜態結構決定的? –

+0

'C'是,我們可以運行請求的服務。例如S3,或谷歌 – whitehead1415

回答

2

鑑於SomeAuthSomeReq,您無法確定它們包裝的類型是否相同。如果有有限個可能性(有限「宇宙」),那麼你可以使用一個GADT來標記它們:

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

SomeReq和模式匹配貼敷在SomeAuth和一個CTag

如果c可以是任何舊事,最好的辦法是使用Data.Typeable,加入Typeable約束到SomeAuthSomeReq構造。一旦你打開它們,你將能夠找出這些類型是否匹配,如果有的話就可以得到它的證據。

+0

感謝您的簡單的解決方案。是否有可能構造SomeAuth的泛型函數?像'mkSomeAuth ::驗證Ç - > SomeAuth' – whitehead1415

+0

更具體地講,我在SomeAuth加入CTAGS去,所以我想這個問題是如何從'(AUTH三)走了 - > C標籤C' – whitehead1415

+0

我回去玩'Typable'作爲一個約束,我有點失落。你能指出一個例子嗎? – whitehead1415