f# iterating : The type 'unit' does not match the type 'char'
I have this function
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开发者_如何转开发
but for some reason the function is expecting a unit list, not a generic one
The type 'unit' does not match the type 'char'
why is this happening ?
As others already pointed out, you probably wanted to use map
instead of iter
. That would work, but it wouldn't be particularly efficient implementation. Here is an alternative way to implement it using list comprehensions:
let randomSelect list toget =
[ let arr = list |> Array.ofList
for _ in 1 .. toget do
yield arr.[rng.Next(arr.Length)] ]
... which could be also written using the map
function, but I find the comprehension syntax more readable:
let randomSelect list toget =
let arr = list |> Array.ofList
[ 1 .. toget ] |> List.map (fun _ -> arr.[rng.Next(arr.Length)] )
To avoid the problem with indexing, the function first converts the list (given as an argument) to array. This will be more efficient if you need to take larger number of elements. For smaller number of elements, using just list and indexing using List.nth
should be fine.
The snippet then generates a sequence of the right length (using 1 .. toget
) and generates a new random element for every element in this input sequence. The values from the input sequence are not needed - they are just use to generate some sequence to start with.
Because List.iter
expects a function which returns unit
and the function fun i -> primeGet i
returns unit
if and only if list
is a list of unit
.
Note that even if your code did compile, it wouldn't do anything, because List.iter
returns unit
and is only used for the function's side-effects, which in this case don't exist. My guess is you probably want to use map
instead of iter
, which returns a list with the results of primeGet
. This would also fix your type error.
One comment:
let getK l k = List.nth l k
let primeGet = getK list
List.nth
is a linear operation. Because F# List is a linked list, it does not have a notion of position. and in your code primeGet
is used in a loop, that makes your the running time of your code quadratic.
精彩评论