Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.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
F#:映射到from non sequence type时,匹配表达式能否不返回序列?_F# - Fatal编程技术网

F#:映射到from non sequence type时,匹配表达式能否不返回序列?

F#:映射到from non sequence type时,匹配表达式能否不返回序列?,f#,F#,我试图创建一个递归函数,该函数有条件地调用自身,目前定义如下: let rec crawlPage (page : String, nestingLevel : int) = HtmlDocument.Load(page) |> fun m -> m.CssSelect("a") |> List.map(fun a -> a.AttributeValue("href")) |> Seq.

我试图创建一个递归函数,该函数有条件地调用自身,目前定义如下:

let rec crawlPage (page : String, nestingLevel : int) =    
    HtmlDocument.Load(page)
    |> fun m -> m.CssSelect("a")
    |> List.map(fun a -> a.AttributeValue("href"))
    |> Seq.distinctBy id
    |> Seq.map (fun x -> baseUrl + x)
    |> Seq.map (fun x -> 
        match nestingLevel with
        // Compiler says it is expecting a but given seq<a> in reference to the recursive call
        | _ when (nestingLevel > 0) -> crawlPage(x, (nestingLevel - 1)) 
        | _ when (nestingLevel <= 0) -> ignore
        | _ -> (* To silence warnigs.*) ignore
    )
let rec crawlPage(页面:字符串,嵌套级别:int)=
HtmlDocument.Load(第页)
|>趣味m->m.CSS选择(“a”)
|>List.map(乐趣a->a.AttributeValue(“href”))
|>序号按id区分
|>Seq.map(乐趣x->baseUrl+x)
|>Seq.map(乐趣x->
将嵌套级别与
//编译器说它需要一个引用递归调用的给定seq
|当(嵌套级别>0)->爬网页面(x,(嵌套级别-1))
|_uu当(嵌套级别忽略)
|_u->(*使警告静音。*)忽略
)

这是
Seq.map(funx->…)
无法处理返回序列,或者匹配条件不能处理返回序列吗?鉴于爬网页由编译器加下划线,似乎match语句无法处理返回的seq,那么如何处理呢?

规则是所有匹配分支必须返回同一类型,因此您必须:

  • ignore
    替换为
    Seq.singleton x
    ,以指示此分支只生成
    x
    本身

  • 最后,concat(平面图)将
    seq
    转换为
    seq

  • 守则是:

    |> Seq.map (fun x -> 
        match nestingLevel with
        | _ when (nestingLevel > 0) -> crawlPage(x, (nestingLevel - 1)) 
        | _ -> Seq.singleton x)
    |> Seq.concat
    
    let rec crawlPage (page : String, nestingLevel : int) = seq {
        let urls = 
            HtmlDocument.Load(page).CssSelect("a")
            |> List.map(fun a -> a.AttributeValue("href"))
            |> Seq.distinctBy id
            |> Seq.map (fun x -> baseUrl + x)
    
        for x in urls do
            if nestingLevel > 0 then
                yield! crawlPage(x, (nestingLevel - 1)) 
            else 
                yield x }
    

    现有的帖子回答了您的具体问题,但我认为值得注意的是,您的代码片段还可以做一些其他更改。其中一些更改是出于个人喜好,但我相信它们使您的代码更简单:

    • 您可以使用序列理解,它允许您使用
      yield!
      (以及使用
      yield
      )很好地处理递归调用
    • 实际上您不需要
      匹配
      ,因为您只有两个分支,使用普通
      if
    • 我还要避免使用
      |>fun m->m.Xyz
      模式,因为这里不需要它
    通过所有这些调整,我更喜欢的代码片段版本是:

    |> Seq.map (fun x -> 
        match nestingLevel with
        | _ when (nestingLevel > 0) -> crawlPage(x, (nestingLevel - 1)) 
        | _ -> Seq.singleton x)
    |> Seq.concat
    
    let rec crawlPage (page : String, nestingLevel : int) = seq {
        let urls = 
            HtmlDocument.Load(page).CssSelect("a")
            |> List.map(fun a -> a.AttributeValue("href"))
            |> Seq.distinctBy id
            |> Seq.map (fun x -> baseUrl + x)
    
        for x in urls do
            if nestingLevel > 0 then
                yield! crawlPage(x, (nestingLevel - 1)) 
            else 
                yield x }