代码之家  ›  专栏  ›  技术社区  ›  McMuttons

F是否与Haskell的接受量相当?

  •  13
  • McMuttons  · 技术社区  · 15 年前

    在haskell中,有一个函数“take n list”,它返回列表中的前n个元素。例如,“sum(take 3 xs)”汇总列表xs中的前三个元素。F是否具有等效物?我希望它是列表函数之一,但我找不到任何匹配的函数。

    3 回复  |  直到 14 年前
        1
  •  15
  •   Joren    15 年前

    是的,它叫 Seq.take . 用法似乎与haskell的相同: 采取的措施 计数源 . 要在列表中使用它,请使用 List.toSeq 第一。 (更新:显然,从评论来看,这是不必要的。)

        2
  •  43
  •   Tomas Petricek    15 年前

    为了澄清一些事情, Seq.take Seq.truncate (如@sepp2k所指出的)第二个函数将为您提供返回的序列 至多 您指定的元素数(但如果序列的长度较小,它将提供较少的元素)。

    生成的序列 采取的措施 如果试图访问超出原始列表长度的元素,函数将引发异常(请注意 采取的措施 函数不会立即抛出异常,因为结果是延迟生成的序列)。

    另外,您不需要显式地将列表转换为序列。在掩护下, list<'a> 是从继承的.NET类 seq<'a> 类型,它是一个接口。类型 SEQ & LT;'A> 实际上只是一个类型别名 IEnumerable<'a> ,因此它由所有其他集合(包括数组、可变列表等)实现。以下代码可以正常工作:

    let list = [ 1 .. 10 ]
    let res = list |> Seq.take 5
    

    但是,如果要获取类型为的结果 list<int> 您需要将序列转换回列表(因为列表的类型比序列更具体):

    let resList = res |> List.ofSeq
    

    我不知道为什么F图书馆不提供 List.take List.truncate . 我想目标是避免为所有类型的集合重新实现整个函数集,因此那些在处理更具体的集合类型时序列实现足够好的函数集只能在 Seq 模块(但这只是我的猜测…)

        3
  •  1
  •   John Reynolds    14 年前

    如其他人所说,采取工作,但清单上的所有顺序操作都是有成本的。对于seq.take,这并不奇怪,因为必须复制列表。

    更值得注意的是,例如,列表上的seq.concat比list.concat花费的时间要长得多。 我认为这意味着,当调用seq.xxx函数时,不仅要将列表作为seq访问,而且还要将复制/转换为seq幕后的列表。

    编辑:我得出上述结论的原因是,这张工作台使用了F Interactive:

    #time "on";;
    let lists = [for i in 0..5000000 -> [i..i+1]];;
    Seq.length (Seq.concat lists);;
    List.length (List.concat lists);;
    

    在我的机器上, List.length 版本需要大约 1.9秒 Seq.length 版本需要大约 3.8秒 (仅对长度行进行几次重复测试的最短时间,不包括列表生成行)。

    推荐文章