簡體   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