gpt4 book ai didi

Haskell FoldM 从列表到单个 Either

转载 作者:行者123 更新时间:2023-12-02 16:38:37 28 4
gpt4 key购买 nike

我正在用 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

模式匹配变量 declsdecls::[Declaration],我使用 Either monad 进行错误跟踪。我的期望

foldM (\输出 decl ->
输出++ (codegenDecl decl)) (empty::ByteString) decls

如果所有声明都正确,则连接所有ByteString,否则返回Left $“Errorwriting a statements”

但我认为,正如打字员提示的那样,我在这里遗漏了一些东西。如果任何一个声明失败,我希望整个模块失败。如果它们全部成功,我想将它们连接成一个 ByteString。

[decls] --------> Right result -------> Right $ foldM (++) accumulator result                                                      |
| ^ |
| -----------------------------------
|
|-----------> Left err ------------> Left $ err

底部似乎是 >>= 运算符对 Either 所做的事情,所以这让我认为有一种时尚的、单一的方式可以在没有 case 等的情况下做我想做的事情。我很想知道这里最好的风格是什么。

最佳答案

这并不是问题的真正答案,因为它没有解决您关于 foldM 的问题...但我什至不会使用 foldM全部。我认为先完成所有的 codegenDecl,然后分别连接结果会更干净。这将有两个优点:

  1. 它将执行单个ByteString串联操作,该操作可以首先构建一个适当大小的缓冲区,然后遍历一次以填充它。这比重复追加更有效,后者必须多次重新遍历早期的 ByteString 并分配许多缓冲区。
  2. 因为它使用可以“做更少事情”的组合器 - mapM 而不是 foldM - 读者可以减少注意力,但仍然可以得出正确的结论发生了什么事。

看起来是这样的:

mconcat <$> mapM codegenDecl decls

关于Haskell FoldM 从列表到单个 Either,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48922049/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com