f#iterating:类型'unit'与'char'类型不匹配

时间:2011-05-07 15:19:44

标签: f# unit-type

我有这个功能

let items = ['a'; 'a'; 'a'; 'a'; 'b'; 'b'; 'a'; 'a'; 'c'; 'd'; 'd'; 'e'; 'e';] 

open System
let rng = new Random()

let randomSelect list toget = let randomList k len = List.init k (fun _ -> rng.Next(1,len))
                              let getK l k = List.nth l k 
                              let primeGet = getK list
                              List.length list
                              |> randomList toget 
                              |> List.iter (fun i -> primeGet i) 

let res23 = randomSelect items 3

但由于某种原因,该功能需要一个单元列表,而不是通用列表

类型'unit'与'char'类型不匹配

为什么会这样?

3 个答案:

答案 0 :(得分:5)

正如其他人已经指出的那样,您可能希望使用map代替iter。这样可行,但实施起来并不是特别有效。以下是使用列表推导实现它的另一种方法:

let randomSelect list toget = 
  [ let arr = list |> Array.ofList
    for _ in 1 .. toget do 
      yield arr.[rng.Next(arr.Length)] ]

...也可以使用map函数编写,但我发现理解语法更具可读性:

let randomSelect list toget = 
  let arr = list |> Array.ofList
  [ 1 .. toget ] |> List.map (fun _ -> arr.[rng.Next(arr.Length)] )

为了避免索引问题,该函数首先将列表(作为参数给出)转换为数组。如果您需要使用更多元素,这将更有效。对于较少数量的元素,使用List.nth只使用列表和索引应该没问题。

然后,片段生成一个正确长度的序列(使用1 .. toget),并为此输入序列中的每个元素生成一个新的随机元素。输入序列中的值不是必需的 - 它们仅用于生成一些序列以开始。

答案 1 :(得分:3)

因为List.iter需要一个返回unit的函数而函数fun i -> primeGet i返回unit当且仅当listunit的列表时}。

请注意,即使您的代码已编译,也不会执行任何操作,因为List.iter返回unit并且仅用于函数的副作用,在这种情况下不存在。我猜你可能想要使用map而不是iter,它会返回一个结果为primeGet的列表。这也可以解决您的类型错误。

答案 2 :(得分:0)

一条评论:

  let getK l k = List.nth l k 
  let primeGet = getK list

List.nth是线性操作。因为F#List是链表,所以它没有位置概念。并且在您的代码中primeGet用于循环,这使您的代码的运行时间成为二次方。