Как разобрать строку в GADT
Я пытаюсь реализовать Combinatory Logic в Haskell, и я хотел бы написать в парсер для языка. У меня проблемы с получением парсера для работы через Parsec. Основная проблема заключается в том, что мне нужен способ обеспечить правильную типизацию объектов, возвращаемых анализатором. У кого-нибудь есть креативные идеи как это сделать?
{-# 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 c@(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
1 ответ
Решение
Я решительный сторонник анализа монотипного представления, а затем применяю фазу проверки типов / разработки, чтобы преобразовать это в типизированное (GADT) представление. Лучший учебник по общей идее, вероятно, от компилятора Леннарта Августсона на основе llvm
Представление для исчисления SKI может выглядеть так
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)