我有这个功能
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'类型不匹配
为什么会这样?
答案 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
当且仅当list
是unit
的列表时}。
请注意,即使您的代码已编译,也不会执行任何操作,因为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
用于循环,这使您的代码的运行时间成为二次方。