Search code examples
f#unit-type

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 ?


Solution

  • 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.