Как правильно выбрать метод перегрузки для композиции функции? - PullRequest
0 голосов
/ 20 февраля 2019

Вот простая композиция функций в F #

let composedFunction = System.Text.Encoding.UTF8.GetBytes >> Array.length
"test" |> composedFunction

Вывод типа правильно определяет тип составной функции string -> int.Но компилятор не может выбрать правильную перегрузку метода System.Text.Encoding.UTF8.GetBytes:

Ошибка FS0041: уникальная перегрузка для метода 'GetBytes' не может быть определена на основе информации о типе до этой программной точки.Тип аннотации могут быть необходимы.Кандидаты:

System.Text.Encoding.GetBytes (chars: char []): byte [],

System.Text.Encoding.GetBytes (s: string): byte [] Blockquote

Есть ли способ составить правильную перегрузку System.Text.Encoding.UTF8.GetBytes, которая принимает строковый параметр?

Или, конечно, я могу сделать следующее

// declare function which calls correct overload and then use it for compostion
let getBytes (s: string) = System.Text.Encoding.UTF8.GetBytes s      
let composedFunction = getBytes >> Array.length

// start composition with ugly lambda
let composedFunction =
  (fun (s: string) -> s) >> System.Text.Encoding.UTF8.GetBytes >> Array.length

Но мне интересно, есть ли способ без дополнительных объявлений функций заставить компилятор правильно выбирать перегрузку в соответствии с предполагаемым типом составной функции string -> int?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Как показывает ваш пример, методы .NET не всегда хорошо сочетаются - я думаю, что идиоматический подход в таких ситуациях - просто использовать стиль .NET, когда вы имеете дело с библиотеками .NET (и использовать функциональный стиль, когда вымы имеем дело с функциональными библиотеками).

В вашем конкретном случае я бы просто определил нормальную функцию с аннотацией типа и получил бы длину, используя член Length, а не функцию:

let composedFunction (s:string) = 
  System.Text.Encoding.UTF8.GetBytes(s).Length

Существующий ответ показывает, как заставить композицию работать с аннотациями типов.Другой трюк, который вы можете сделать (который я бы определенно не использовал на практике), заключается в том, что вы можете добавить функцию идентификации на string в композицию, чтобы ограничить типы:

let composedFunction = id<string> >> System.Text.Encoding.UTF8.GetBytes >> Array.length

Этозабавно, что это работает, но, как я уже сказал, я бы никогда не использовал это, потому что обычную функцию, как определено выше, гораздо легче понять.

0 голосов
/ 21 февраля 2019

Вы всегда можете добавить аннотации:

let composedFunction : string -> _ = System.Text.Encoding.UTF8.GetBytes >> Array.length

или

let composedFunction = (System.Text.Encoding.UTF8.GetBytes : string -> _) >> Array.length
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...