Как я могу следовать предложению F # Lint использовать `id` - PullRequest
0 голосов
/ 11 октября 2018

Я сравниваю два списка фангов.Поскольку я больше знаком с Linq, чем с F #, я сделал это: let r1 = (rows1.Zip (rows2, fun r1 r2 -> rowComparer r1 r2)) .All (fun f -> f)

Это вызывает две жалобы со стороны F # linter. Lint: If `rowComparer` has no mutable arguments partially applied then the lambda can be removed. Lint: `fun x -> x` might be able to be refactored into `id`.

Из них я мог понять последнее и попробовал это: let r1 = (rows1.Zip (rows2, fun r1 r2 -> rowComparer r1 r2)) .All id Но это заставило компилятор F # жаловаться:

Ожидается, что это выражение будет иметь тип 'System.Func'
но здесь есть тип' 'a ->' a '

Может кто-нибудь сказать, как этот код может быть более праведным?

Ответы [ 2 ]

0 голосов
/ 11 октября 2018

Вы можете предоставить стандартную функцию id в качестве аргумента, если создаете экземпляр System.Func с правильным количеством параметров универсального типа из него.Используя лямбда-выражение, компилятор F # сделает это за вас.

open System.Linq
let foo rowComparer (rows1 : seq<_>) (rows2 : seq<_>) =
    (rows1.Zip (rows2, fun r1 r2 -> rowComparer r1 r2)).All(System.Func<_,_>(id))
// val foo :
//   rowComparer:('a -> 'b -> bool) -> rows1:seq<'a> -> rows2:seq<'b> -> bool
0 голосов
/ 11 октября 2018

Я бы предложил использовать модули F # List или Seq вместо методов LINQ.Тогда вы сможете использовать типы F #, такие как 'a -> 'a вместо System.Func<'a, 'a>, и вы можете передать id в функцию forAll.Если бы вы могли опубликовать полный пример, было бы легче дать вам полный ответ, но я думаю, что что-то вроде этого будет примерно эквивалентно тому, что вы делаете с LINQ:

let compare (rowComparer: ('a * 'a) -> bool) rows = 
    Seq.zip rows >> Seq.map rowComparer >> Seq.forall id

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

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

let compareEqual = compare (fun (a,b) -> a = b) 
compareEqual [0; 1; 2] [0; 1; 2] // true
compareEqual [0; 1; 2] [2; 1; 2] // false
...