Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell将数据从列表转换为单个_Haskell - Fatal编程技术网

Haskell将数据从列表转换为单个

Haskell将数据从列表转换为单个,haskell,Haskell,我在Haskell写一个类似的翻译,到目前为止非常有趣。我正在进行Codegen步骤(获取解析器结果,将其打印到代码中),我尝试做的一件事是: 我有模块,我的模块有声明 codegen :: Module -> Either String ByteString codegen Module { what = "module", declarations = decls } = Right $ foldM (\output decl -> output ++ (codegenD

我在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]
,我正在使用其中一个monad进行错误跟踪。我对你的期望是什么

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

如果所有声明都正确,则返回所有bytestring,或者返回一个
Left$“Error write a declaration”

但是我想我在这里遗漏了一些东西,就像打字员抱怨的那样。如果其中一个声明失败,我希望整个模块都失败。如果它们都成功了,我想将它们连接成一个ByteString

[decls] --------> Right result -------> Right $ foldM (++) accumulator result                                                      |
    |                 ^                                 |
    |                 -----------------------------------
    |
    |-----------> Left err ------------> Left $ err
底部的部分似乎是>>=操作符所做的,因此我认为有一种时尚的、一元的方式来做我想做的事情,而无需案例等等。我很想知道这里最好的款式是什么。

  • (++)::[a]->[a]->[a]
    附加列表

  • output::ByteString

  • codegenDecl decl::通过testring的字符串之一

输出
(++)
的第一个参数的预期类型不匹配(除非在某个地方重新定义了它,例如在基本前奏曲中),并且
codegenDecl
(++)
的第二个参数的预期类型不匹配

此lambda应进行类型检查(使用
数据中的
()
。Monoid
):

\output decl->fmap(输出)(codegenDecl decl)

这并不是对这个问题的真正回答,因为它没有解决您关于
foldM
的问题。。。但我甚至不会使用
foldM
。我认为执行所有
codegenDecl
ing,然后分别连接结果更为简洁。这将有两个好处:

  • 它将执行一个
    ByteString
    串联操作,该操作可以首先构建一个大小合适的缓冲区,然后遍历它一次以填充它。这将比重复追加更有效,重复追加必须通过testring多次提前重新访问
    并分配许多缓冲区
  • 因为它使用了可以“做更少事情”的组合词--
    mapM
    而不是
    foldM
    ,所以读者可以减少注意力,仍然可以对正在发生的事情得出正确的结论
  • 下面是它的外观:

    mconcat <$> mapM codegenDecl decls
    
    mconcat mapM codegenDecl decls
    
    关于“打字机投诉”:发生这种情况时,您应该始终发布(完整)错误消息。否则,您会强迫读者在头脑中执行类型检查,试图找出错误所在,或者试图从代码中构建MCVE——这两种方法都需要付出不平凡的努力。这会减少有人回答您问题的可能性。您想要类似于
    concat mapM codegenDecl decls
    的内容吗?太好了,谢谢!因此,需要澄清的是,如果结果数组有多个“左错误”,mconcat实际上不会concat对吗?@rausted正确:只要
    codegenDecl
    为其中一个
    decls
    返回
    Left
    ,整个计算将立即中止并返回
    Left
    mconcat <$> mapM codegenDecl decls