Почему вывод равен <seq>, а не int в F #? - PullRequest
0 голосов
/ 11 июня 2018

Это мой код:

 Csv.GetSample().Rows
 |> Seq.groupBy (fun row -> row.STATE,row.INCOME,row.CHILDREN)
 |> Seq.map (fun ((state,income,children),data) -> 
    let pctrepub = data|> Seq.map (fun row -> (100.0 - float row.otherparty)) 
    ((state,income,children),pctrepub))
 |> List.ofSeq

Это мой идеальный результат:

   (("TX", "51522", "0"), 65.0);
   (("AL", "6481", "1"), 51.4);
   (("MO", "78921", "1"), 25.1);
   (("TN", "12000", "4"), 62.1);
   (("PA", "79850", "2"), 41.2);
   (("NY", "79215", "1"), 31.0);
   (("CA", "79045", "2"), 50.5);

Вот чем я заканчиваю:

   (("TX", "51522", "0"), <seq>);
   (("AL", "6481", "1"), <seq>);
   (("MO", "78921", "1"), <seq>);
   (("TN", "12000", "4"), <seq>);
   (("PA", "79850", "2"), <seq>);
   (("NY", "79215", "1"), <seq>);
   (("CA", "79045", "2"), <seq>);

Почему последняя строка значений отображается как <seq> и как мне это исправить?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

В другом месте вы упомянули, что вы новичок в F # (начал изучать его восемь дней назад), поэтому вот краткое руководство по чтению документации по F #, которая может помочь вам самостоятельно ответить на некоторые из этих вопросов.Давайте посмотрим на документацию для модуля Seq .В нем перечислено множество функций, которые можно вызывать для последовательностей: append, average, averageBy, filter, map, groupBy ... Все они имеют разные сигнатуры типов и сигнатуру типакаждой функции является ключом к тому, что она будет делать.Давайте рассмотрим несколько примеров:

  • average: seq<^T> -> ^T - Возвращает среднее значение элементов в последовательности.
  • averageBy:('T -> ^U) -> seq<'T> -> ^U - Возвращает среднее значение результатов, полученных при применении функции к каждому элементу последовательности.
  • map: ('T -> 'U) -> seq<'T> -> seq<'U> - СоздаетНовая коллекция, элементами которой являются результаты применения данной функции к каждому из элементов коллекции.

Сначала average, так как это проще всего.Стрелка -> в типе signure говорит вам, что это функция.Ввод слева от стрелки, а выход справа от стрелки.Таким образом, сигнатура типа означает, что эта функция принимает seq<^T> и возвращает элемент типа ^T.Символы ^ или ' перед именем типа T означают, что это универсальный тип, который будет преобразовываться в любой тип, который у вас есть при запуске кода: int, string, tuple и т. Д.Так что T - это просто название для любого типа, который у вас есть: если у вас есть целые числа, это функция seq<int> -> intЕсли у вас есть строки, это функция seq<string> -> string и так далее.(Символ ^ перед типом означает, что он будет разрешен во время компиляции, тогда как символ ' перед ним означает, что он будет разрешен во время выполнения. Вам не нужно беспокоиться об этом различиидо тех пор, пока у вас не будет намного больше опыта с F #, а пока просто рассматривайте любой из них как флаг, который означает «Это универсальный тип»).Таким образом, сигнатура типа функции average говорит вам, что она принимает последовательность значений и возвращает одно значение .

Now, averageBy.Это сложнее.Во-первых, здесь есть еще стрелки.Это связано с концепцией под названием curry , которая очень хорошо объяснена в ссылке, поэтому я не буду вдаваться в подробности.На начальном уровне вы должны думать о том, что идет после стрелки final , как о выходе функции, а все остальные типы как о входах функции (которые будут разделены стрелками).).Другими словами, подпись типа, подобную int -> char -> string, должна читаться как «это функция, которая принимает два ввода: int первый и char второй и возвращает string

Но видите ли вы круглые скобки вокруг бита ('T -> ^U) в сигнатуре averageBy?Эти скобки означают только то, что они имеют в виду в математике: прочитайте эту часть отдельно.Таким образом, первый параметр averageBy имеет тип ('T -> ^U).Второй параметр averageBy имеет тип seq<'T>, а вывод имеет тип ^U.Теперь, если вы посмотрите на сигнатуру типа ('T -> ^U), в ней есть стрелка, так что это функция.В частности, это функция, которая принимает вещь универсального типа T и возвращает вещь универсального типа U.(Как я уже говорил ранее, не беспокойтесь о различии ' против ^ прямо сейчас).Второй параметр представляет собой последовательность элементов типа T, а выходные данные имеют тип U.Эта сигнатура типа плюс имя дает вам подсказку о том, как работает функция: она будет просматривать последовательность вещей типа T, и для каждого она будет вызывать функцию для преобразования этой вещи Tв вещь типа U.Затем он возвращает единственное значение U в качестве выходных данных: по имени вы можете заключить, что единственное значение, которое оно возвращает, будет средним значением всех значений U, полученных функцией 'T -> ^U.

Таким образом, сигнатура типа ('T -> ^U) -> seq<'T> -> ^U означает, что первый аргумент является функцией, которая принимает T и возвращает U, второй аргумент представляет собой последовательность элементов типа T, а функция возвращаетодин элемент типа U.

Наконец, давайте посмотрим на map.Его сигнатура типа выглядит довольно похоже на averageBy: первый параметр снова является функцией, которая принимает T и преобразует его в U.Второй параметр снова представляет собой последовательность T элементов.Но на этот раз вместо одного значения результатом map будет последовательность из U значений.

И так, посмотрев документацию , мы можем видеть, что если вы не хотите, чтобы последовательность выводилась, Seq.map - это неправильная вещь для вызова.В модуле Seq есть изумительный список функций, так что вы можете быть немного ошеломлены.Но внимательный взгляд на сигнатуры типов и понимание того, что означает каждый из них, - это большая помощь в определении того, кто будет делать то, что вы хотите с вашими данными.И чтение через https://fsharpforfunandprofit.com/posts/list-module-functions/ также поможет вам: F # осторожно рассматривает модули List, Seq и Array как , очень похожие друг на друга , включая почтивсе те же функции.Поэтому, если вы знаете, что делает List.averageBy, вы также будете знать, что делают Seq.averageBy и Array.averageBy: единственная разница будет в том, какой тип коллекции они принимают в качестве входных данных.Поэтому, хотя на этой странице говорится о списках, ее рекомендации также применимы и к Seq.

Кто-то уже ответил на ваш вопрос в комментариях (просто сделайте Seq.map (fun row -> (row.STATE,row.INCOME,row.CHILDREN), 100.0 - float row.otherparty), и вы должны получить желаемый результат), поэтомуЯ не буду вдаваться в подробности там.Надеюсь, что время, которое я потратил на написание этой статьи, будет полезно для вас, чтобы помочь вам лучше понять вещи, так что вы сможете ответить на свои вопросы в будущем и вам не придется полагаться на вопрос о переполнении стека (изатем ждем, иногда часы, ответов).

0 голосов
/ 11 июня 2018

Последний элемент кортежа - pctrepub, который является результатом вызова Seq.map, а Seq.map возвращает последовательность, а не число.Поэтому совершенно не удивительно, что последний элемент кортежа - это последовательность.

Что касается того, как это исправить, информации недостаточно: я вижу, что вы хотите получить число вместо последовательностей, но вы 'Я не говорю, откуда взялись цифры, поэтому я не могу вам помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...