2013-03-13 11 views
3

以下程序類型檢查和編譯:評價一個AST(作爲GADT)與如箭頭原子值

import Control.Arrow 

data Ns = Na | Nb | Nc | Nd deriving Show 

data Net a where 
    Uni :: a -> Net a 
    Serial :: Net a -> Net a -> Net a 
    Branch :: Show a => Net a -> Net (Net a, Net a) 

deriving instance Show a => Show (Net a) 

eval :: (Arrow a) => Net c -> a b (Net c) 
eval (Uni m) = arr (const (Uni m)) 
eval (Serial m n) = eval m >>> eval n 
--eval (Branch m) = eval m &&& eval m 

example = Serial (Serial (Uni Na) (Uni Nb)) (Serial (Uni Nc) (Uni Nd)) 

main = do 
    putStrLn $ show (app (eval example, Na)) 

然而,當我嘗試添加的情況下爲eval (Branch m),類型檢查彈出。類型

Arrow a => a b (Net d) 

的事情的預期,但當然我的方式有很

Arrow a => a b (c',c'') 

沒有人有怎樣寫eval (Branch m)有何建議?

編輯我

針對@sabauma評論,我認爲eval類型簽名將不得不改變,但我不知道它應該是什麼。

編輯II

下面是應該發生的事情爲例:

branch = Branch example 
app (eval branch, Na) 

應該給,

Uni (Uni Na,Uni Na) 

這是@sabauma的建議一樣。

+3

你確定發佈的代碼類型檢查?即使最後一個案例已被註釋掉,我仍然會遇到一個類型錯誤,涉及您在「eval」上簽名。 GHC推斷出類型'eval :: Arrow a => Net a - > a(Net a)(Net a)'。 – sabauma 2013-03-13 13:52:20

+0

@sabauma我糾正了'eval'的類型聲明。至少,在嘗試添加'eval(Branch m)' – lafras 2013-03-13 14:16:59

+1

之前,將它改回原來的樣子。您應該明確地添加一些預期輸出的示例或對語義的進一步解釋。根據您提供的信息,很難猜測出「eval」應該做什麼。 – phg 2013-03-13 15:21:20

回答

3

一種可能性是

eval :: (Arrow a) => Net c -> a b (Net c) 
eval (Uni m)  = arr (const (Uni m)) 
eval (Serial m n) = eval m >>> eval n 
eval (Branch m) = (eval m &&& eval m) >>> arr Uni 

我不知道這是否具有所期望的行爲,但它typechecks而不是 平凡解。這可以讓您在不改變類型簽名的情況下離開。

+0

這看起來不錯。 'eval(Branch(Uni Na))'給了我所期望的,即'Uni(Uni Na,Uni Na)'。我只需要思考一下語義。 – lafras 2013-03-13 14:55:01

2

雖然我不是你的代碼的目的完全肯定,而這可能不是你以後,下面typechecks:

eval :: Arrow a => Net c -> a b (Net c) 
eval (Uni m)  = arr (const (Uni m)) 
eval (Serial m n) = eval m >>> eval n 
eval (Branch m) = arr (const (Branch m)) 
當然

arr . const平凡工程EVAL,但現在我幾乎是積極的,這不是你想要的。

3

我的猜測是對redifine Branch採取兩個參數(因爲分支某種程度上意味着對我來說):

data Net a where 
    Uni :: a -> Net a 
    Serial :: Net a -> Net a -> Net a 
    Branch :: Show a => Net a -> Net a -> Net (Net a, Net a) 

導致

eval :: (Arrow a) => Net c -> a b (Net c) 
eval (Uni m) = arr (const $ Uni m) 
eval (Serial m n) = eval m >>> eval n 
eval (Branch l r) = (eval l) &&& (eval r) >>> arr (uncurry Branch) 

但我不能說,如果這種改變對你來說很有意義。你可能應該解釋一下你的類型是如何使用的。