需要基本的do块语法说明

问题描述

在ghci中,我写道:

 let x = do
    i <- [1..5]
    j <- [2..4]
    return i 

预期结果:

[1,2,3,4,5]

实际结果:

[1,1,5,5]

我不明白该输出背后的逻辑。我认为原因可能与monad有关,但是我对函数式编程非常陌生,希望有人能对此有所解释。

我还尝试了List理解中的等价形式,结果是相同的,这意味着我在这里误解了一些基本知识。

解决方法

这是因为do机制并不关心(幸运地)最里面的代码是否实际上引用了循环变量中的某些变量。

无论您使用最里面的代码,您总会得到3 * 5 = 15个值:

#include  <vector>
#include  <iostream>

int main()
{
    std::vector<int>  vi{1,2,3,4,5};
    std::vector<int>  vj{2,4};

    for (int i: vi)
        for (int j: vj)
            std::cout << i << ",";

    std::cout << std::endl;

    return EXIT_SUCCESS;
}

据我所知,这是Haskell与C,C ++,Fortran,Python共享的完全标准的行为。

等效的C ++示例:

$ ./a.out
1,1,5,$ 

C ++输出:

$("#td-apt").on('click',function() {
    getModalData();
    $("#data-modal").modal('toggle');
});

function getModalData () {
    $.ajax({
        type: "POST",url: "/function/Data",headers: {
            'X-CSRF-Token': $('input[name="_csrfToken"]').val()
        },dataType: "json",success: function(data) {
            console.log('success')
        },error: function() {
            alert('Error');
        }
    });
}
,

我还尝试了List-comprehension中的等价形式,结果是相同的

好主意。碰巧的是,对于列表,do表示法与列表理解功能完全相同。 (实际上,a syntactic extension允许您对任何monad使用列表理解表示法,就像您可以对任何monad使用do表示法一样。)

因此,您在问为什么[a | a<-[0,1],b<-[2,3]]给出[0,1]而不是[0,1]。令人惊讶的方式是,如果您像数学中那样将列表理解视为 set comprehensions 。但是列表不是集合,尽管Haskellers确实经常使用列表作为集合的临时替代品。如果列表理解作为集合理解,那么

  [x | x <- [0,0]]

还应仅产生[0,1]作为其结果(或至少应产生与[x|x<-[0,1]]相同的 结果)。

通常,这种除草重复项需要进行相等性检查,并且如果要使其高效,还可以使用排序或哈希方法。列表不做任何事情,因此,如果您想要类似集合的行为,则应使用集合实现数据结构。 SetHashSet是最常见的。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...