2012-10-17 215 views
4

我試圖在Haskell中實現組合邏輯,並且我想寫入語言的解析器。我無法通過Parsec解析器工作。基本的問題是我需要一種方法來確保解析器返回的對象輸入正確。有沒有人有關於如何做到這一點的創意?如何將字符串解析爲GADT

{-# Language GeneralizedNewtypeDeriving #-} 

import qualified Data.Map as Map 
import qualified Text.ParserCombinators.Parsec as P 
import Text.Parsec.Token (parens) 
import Text.ParserCombinators.Parsec ((<|>)) 
import Control.Applicative ((<$>), (<*>), (*>), (<*)) 


data CTree = CApp CTree CTree | CNode String deriving (Eq, Read) 
instance Show CTree where 
    show [email protected](CApp x y) = showL c 
     where showL (CApp x' y')= "(" ++ showL x' ++ " " ++ showR y' ++ ")" 
       showL (CNode s) = s 
       showR (CApp x' y') = "(" ++ showL x' ++ " " ++ showR y' ++ ")" 
       showR (CNode s) = s 

    show (CNode s) = s 

-- | Parser 
parseC :: String -> Maybe CTree 
parseC s = extract$ P.parse expr "combinator_string" s 
      where extract (Right r) = Just r 
       extract (Left e) = Nothing 


expr :: P.CharParser() CTree 
expr = P.try (CApp <$> (CApp <$> term <*> term) <*> expr) 
     <|> P.try (CApp <$> term <*> term) 
     <|> term 


term = P.spaces *> (node <|> P.string "(" *> expr <* P.string ")") 


node :: P.CharParser() CTree 
node = CNode <$> (P.many1 $ P.noneOf "() ") 

eval (CApp (CNode "I") x) = x 
eval (CApp (CApp (CApp (CNode "S") f) g) x) = 
    (CApp (CApp f x) (CApp g x)) 
eval (CApp (CApp (CApp (CNode "B") f) g) x) = 
    (CApp f (CApp g x)) 
eval (CApp (CApp (CApp (CNode "C") f) g) x) = 
    (CApp (CApp f x) g) 
eval x = x 
+0

你會希望使用一個存在或上位延續(因爲不可能可能需要這裏的imponedicative類型)。有一些例子(不是特別的解析,但想法是相似的)在http://stackoverflow.com/questions/7978191/how-to-make-a-type-with-restrictions/7984155#7984155。 – copumpkin

回答

3

我解析到一個monotyped表示,然後施加一個類型檢查/細化階段將其轉換成輸入(GADT)表示的大力提倡。在總體思路的最好的教程可能是Lennart Augustsson's llvm based compiler

一種滑雪演算表示可能看起來像

data TyComb t where 
    TyS :: TyComb ((a -> b -> c) -> (a -> b) -> a -> c) 
    TyK :: TyComb (a -> b -> a) 
    TyI :: TyComb (a -> a) 
    TyApp :: TyComb (a -> b) -> TyComb a -> TyComb b 

evalTyComb :: TyComb t -> t 
evalTyComb TyS   = \x y z -> (x z) (y z) 
evalTyComb TyK   = const 
evalTyComb TyI   = id 
evalTyComb (TyApp a b) = (evalTyComb a) (evalTyComb b)