【发布时间】:2018-02-22 07:46:06
【问题描述】:
我正在用 Haskell 编写某种解释器,到目前为止它非常有趣。我在 Codegen 步骤(获取解析器结果,将其漂亮地打印到代码中),我尝试做的一件事如下:
我有模块,我的模块有声明。
codegen :: Module -> Either String ByteString
codegen Module { what = "module", declarations = decls } = Right $ foldM (\output decl ->
output ++ (codegenDecl decl)) (empty :: ByteString) decls -- generate declarations
codegen Module { what = s } = Left $ "Bad module 'what' key " ++ s
codegenDecl :: Declaration -> Either String ByteString
codegenDecl Declaration { what = dt, name = dn, argnames = Just al, constructors = Just lc } = Right $ "Declaration " ++ dn ++ " of type " ++ dt
模式匹配变量decls 是decls :: [Declaration],我使用Either monad 进行错误跟踪。我对
foldM (\output decl ->
output ++ (codegenDecl decl)) (empty :: ByteString) decls
如果所有声明都正确,则连接所有字节字符串,或者返回Left $ "Error writing a declaration"
但我认为我在这里遗漏了一些东西,因为类型检查器会抱怨。如果任何一个声明失败,我希望整个模块失败。如果它们都成功了,我想将它们连接成一个 ByteString。
[decls] --------> Right result -------> Right $ foldM (++) accumulator result |
| ^ |
| -----------------------------------
|
|-----------> Left err ------------> Left $ err
底部部分似乎是 >>= 运算符为 Either 所做的,所以这让我觉得有一种时尚的、单子的方式来做我想做的事,而无需案例等。我很想知道这里最好的风格是什么。
【问题讨论】:
-
关于“类型检查器抱怨”:当这种情况发生时,您应该始终发布(完整)错误消息。否则,你会强迫读者在头脑中执行类型检查,试图找出问题所在,或者试图从你的代码构建一个 MCVE——两者都需要不小的努力。这样就不太可能有人回答您的问题。
-
你想要
concat <$> mapM codegenDecl decls这样的东西吗?
标签: haskell