F#中的ReplicateM等效

时间:2014-05-14 14:42:38

标签: haskell f#

ReplicateMHaskellF#)是否有任何等效函数?

示例:

replicateM 2 [1,2,3] = 
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]

2 个答案:

答案 0 :(得分:4)

您可以在F#+中找到它,并为ListSeq定义:

#r @"C:\packages\FsControl.2.0.0-CI00073\lib\net40\FsControl.dll"
#r @"C:\packages\FSharpPlus.1.0.0-CI00015\lib\net40\FSharpPlus.dll"

open FSharpPlus

List.replicateM 2 [1;2;3]

// val it : List<int list> =
//  [[1; 1]; [1; 2]; [1; 3]; [2; 1]; [2; 2]; [2; 3]; [3; 1]; [3; 2]; [3; 3]]

Seq.replicateM 2 [1;2;3]
// val it : seq<int> list =
// [seq [1; 1]; seq [1; 2]; seq [1; 3]; seq [2; 1]; seq [2; 2]; seq [2; 3];
//   seq [3; 1]; seq [3; 2]; seq [3; 3]]

如果您正在从Haskell进行翻译,那么有一个带有该函数和其他Haskell绑定的Compatibility.Haskell模块。

事实上,最后一个参数可以是列表或任何其他Applicative,但如果您不想使用该库,并且您对仅适用于list的版本感到满意,那么您可以像这样定义:

let replicateM n x = 
    let k m m' = List.collect (fun x -> 
        List.collect(fun xs -> 
            [List.Cons(x,xs)]) m') m       
    List.foldBack k (List.replicate n x) [[]]

答案 1 :(得分:1)

该功能在标准库中不可用,因此如果您不想依赖外部库,则需要自己编写。最简单的实现如下:

let rec replicateM m l = seq {
  if m = 1 then 
    // If we want just one replication, generate singleton lists
    for v in l do yield [v]
  else 
    // Otherwise, iterate over all lists with m-1 replicates
    for s in replicateM (m - 1) l do
      // .. and append elements from 'l' to the front
      for v in l do yield v::s }