繁体   English   中英

F#是否与Haskell相当?

[英]Does F# have an equivalent to Haskell's take?

在Haskell中,有一个函数“take n list”,它返回列表中的前n个元素。 例如,“sum(take 3 xs)”总结了列表xs中的前三个元素。 F#有同等价值吗? 我希望它是List函数之一,但我找不到任何似乎匹配的东西。

为了澄清一些事情, Seq.takeSeq.truncate之间的差异(由@ sepp2k指出)是第二个将给你一个序列,它最多返回你指定的元素数量(但如果长度为顺序较少,它会给你更少的元素)。

如果您尝试访问超出原始列表长度的元素,则生成的序列Seq.take函数将抛出异常(请注意, Seq.take函数不会立即抛出异常,因为结果是延迟生成的序列)。

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

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

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

let resList = res |> List.ofSeq

我不确定为什么F#库不提供List.takeList.truncate 我的目标是避免为所有类型的集合重新实现整个函数集,所以那些使用更具体的集合类型的序列实现足够好的那些只在Seq模块中可用(但这只是我的猜测...)

是的,它被称为Seq.take 用法似乎与Haskell的相同: Seq.take 计数源 要在列表中使用它, List.toSeq首先使用 List.toSeq (更新:显然,从评论来看,这不是必需的。)

Seq.take正如其他人已经说过的那样有效,但是列表上的所有Seq操作都需要付出代价。 在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秒 (仅对长度行进行一些重复测试的最短时间,不包括列表生成行)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM