如何声明这个问题的类型?



我正在尝试用一些原语和用户定义的函数创建一个简单的编程语言。

这些是我创建的类型:

data Type = IntT | BoolT
data Value = IntV Int | BoolV Bool | OperatorCall String [Value]
data Expr = LetE String Value | ProcedureCall String [Value]

可以看到,我将函数分为操作符(返回值)和过程(不返回任何东西,充当表达式而不是值)。函数调用包含被调用函数的字符串id和传递的参数列表。另外,程序只是一个表达式列表(为了简单起见,我省略了用户定义的函数)

我的问题来自于我需要写一个函数来解析来自字符串的函数调用:

parseFunctionCall :: String -> ???
...

函数的返回类型可以是Value(用于操作符调用)或Expr(用于过程调用)。这个函数相当复杂,我宁愿避免写两次,或者用Either返回类型污染它。我该怎么办?我怎样才能改变我的类型,从而干净利落地实现这个目标?可能是这样的,但我不认为这是正确的方法:

type FunctionCall = (String, [Value])
data Value = ... | OperatorCall FunctionCall
data Expr = ... | ProcedureCall FunctionCall
parseAsFunctionCall :: String -> FunctionCall
...

您可以让函数调用解析器返回(String, [Value]),并让调用者将其修复为他们最喜欢的任何数据结构—在您的情况下,如果解析值则应用(s, vs) -> OperatorCall s vs,如果解析表达式则应用(s, vs) -> ProcedureCall s vs

parseFunctionCall :: Parser (String, [Value])
parseLiteralInt :: Parser Int
parseLiteralBool :: Parser Bool
parseLet :: Parser (String, Value)
(parseFunctionCall, parseLiteralInt, parseBool, parseLet) = {- ... -}
parseValue :: Parser Value
parseValue =
(((s, vs) -> OperatorCall s vs) <$> parseFunctionCall)
<|>
(IntV <$> parseLiteralInt)
<|>
(BoolV <$> parseLiteralBool)
parseExpr :: Parser Expr
(((s, vs) -> ProcedureCall s vs) <$> parseFunctionCall)
<|>
(((s, v) -> Let s v) <$> parseLet)

相关内容

最新更新