在编译期间评估表达式并将运行时错误视为编译错误
Eval expression during compilation and treat runtime errors as compilation errors
我正在 Haskell 中开发一个简单的编程语言解释器,但在定义标准库时遇到了一些麻烦。我希望它在顶层被定义为静态字符串并与我的解释器一起编译:
stdLibStr :: String
stdLibStr = "id a := a;;"
parse :: String -> Either Error UntypedModule
typecheck :: UntypedModule -> Either Error TypedModule
-- constexpr
stdLib :: TypedModule
stdLib = either (error . show) id $ parse stdLibStr >>= typecheck
但是,上面的模型不会在编译期间计算 stdLib
。此外,它不会给我任何关于解析错误和类型检查错误的反馈。我希望我的解释器在 parse
或 typecheck
returns Left
中不编译,如下例所示:
stdLibString = "≠²³¢©œęæśð"
-- Compilation error: "cannot parse definition"
stdLib = either (error . show) id $ parse stdLibStr >>= typecheck
我在为我的语言定义 QuasiQuotation 时试图使用 fail
来实现这一点,但是由于其他一些问题,不可能有这样的引用。
怎样做最方便?
正如评论中所建议的,模板 Haskell 是执行此操作的方法。下面的函数处理这两种情况:
compileTime :: Lift a => Either String a -> Q Exp
compileTime (Right a) = lift a
compileTime (Left err) = fail err
可以调用为$(compileTime (typecheck =<< parse stdLibStr))
。或者它足够短,可以内联为 either fail lift
。
要使用它,在 $()
中调用的任何函数都必须在与调用它的地方不同的模块中定义。
我正在 Haskell 中开发一个简单的编程语言解释器,但在定义标准库时遇到了一些麻烦。我希望它在顶层被定义为静态字符串并与我的解释器一起编译:
stdLibStr :: String
stdLibStr = "id a := a;;"
parse :: String -> Either Error UntypedModule
typecheck :: UntypedModule -> Either Error TypedModule
-- constexpr
stdLib :: TypedModule
stdLib = either (error . show) id $ parse stdLibStr >>= typecheck
但是,上面的模型不会在编译期间计算 stdLib
。此外,它不会给我任何关于解析错误和类型检查错误的反馈。我希望我的解释器在 parse
或 typecheck
returns Left
中不编译,如下例所示:
stdLibString = "≠²³¢©œęæśð"
-- Compilation error: "cannot parse definition"
stdLib = either (error . show) id $ parse stdLibStr >>= typecheck
我在为我的语言定义 QuasiQuotation 时试图使用 fail
来实现这一点,但是由于其他一些问题,不可能有这样的引用。
怎样做最方便?
正如评论中所建议的,模板 Haskell 是执行此操作的方法。下面的函数处理这两种情况:
compileTime :: Lift a => Either String a -> Q Exp
compileTime (Right a) = lift a
compileTime (Left err) = fail err
可以调用为$(compileTime (typecheck =<< parse stdLibStr))
。或者它足够短,可以内联为 either fail lift
。
要使用它,在 $()
中调用的任何函数都必须在与调用它的地方不同的模块中定义。