повторение f #: тип ‘unit’ не соответствует типу ‘char’

#f# #unit-type

#f# #тип единицы измерения

Вопрос:

У меня есть эта функция

 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’

почему это происходит?

Ответ №1:

Как уже указывали другие, вы, вероятно, хотели использовать 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 ) и генерирует новый случайный элемент для каждого элемента в этой входной последовательности. Значения из входной последовательности не нужны — они просто используются для генерации некоторой последовательности для начала.

Ответ №2:

Потому что List.iter ожидает функцию, которая возвращает unit , а функция fun i -> primeGet i возвращает unit тогда и только тогда, когда list является списком unit .

Обратите внимание, что даже если бы ваш код действительно компилировался, он ничего бы не сделал, потому что List.iter возвращает unit и используется только для побочных эффектов функции, которых в данном случае не существует. Я предполагаю, что вы, вероятно, хотите использовать map вместо iter , который возвращает список с результатами primeGet . Это также исправило бы вашу ошибку типа.

Ответ №3:

Один комментарий:

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

List.nth это линейная операция. Поскольку F # List является связанным списком, у него нет понятия позиции. и в вашем коде primeGet используется в цикле, что делает время выполнения вашего кода квадратичным.

Комментарии:

1. Я знаю, что это вообще неэффективно. но я хочу сначала заставить это работать, а затем улучшить