Это не для практической необходимости, а скорее для того, чтобы попытаться чему-то научиться.
Я использую выражение FSToolKit asyncResult, которое очень удобно, и я хотел бы знать, есть ли способ «объединить» выражения, такие как асинхронный и результат здесь, или нужно написать собственное выражение ?
Вот пример моей функции для установки IP-адреса в поддомен с помощью CloudFlare:
let setSubdomainToIpAsync zoneName url ip =
let decodeResult (r: CloudFlareResult<'a>) =
match r.Success with
| true -> Ok r.Result
| false -> Error r.Errors.[0].Message
let getZoneAsync (client: CloudFlareClient) =
asyncResult {
let! r = client.Zones.GetAsync()
let! d = decodeResult r
return!
match d |> Seq.filter (fun x -> x.Name = zoneName) |> Seq.toList with
| z::_ -> Ok z // take the first one
| _ -> Error $"zone '{zoneName}' not found"
}
let getRecordsAsync (client: CloudFlareClient) zoneId =
asyncResult {
let! r = client.Zones.DnsRecords.GetAsync(zoneId)
return! decodeResult r
}
let updateRecordAsync (client: CloudFlareClient) zoneId (records: DnsRecord seq) =
asyncResult {
return!
match records |> Seq.filter (fun x -> x.Name = url) |> Seq.toList with
| r::_ -> client.Zones.DnsRecords.UpdateAsync(zoneId, r.Id, ModifiedDnsRecord(Name = url, Content = ip, Type = DnsRecordType.A, Proxied = true))
| [] -> client.Zones.DnsRecords.AddAsync(zoneId, NewDnsRecord(Name = url, Content = ip, Proxied = true))
}
asyncResult {
use client = new CloudFlareClient(Credentials.CloudFlare.Email, Credentials.CloudFlare.Key)
let! zone = getZoneAsync client
let! records = getRecordsAsync client zone.Id
let! update = updateRecordAsync client zone.Id records
return! decodeResult update
}
Он взаимодействует с библиотекой C#, которая обрабатывает все вызовы API CloudFlare и возвращает объект CloudFlareResult с флагом успеха, результатом и ошибкой.
Я переназначил этот тип на тип Result‹'a, string›:
let decodeResult (r: CloudFlareResult<'a>) =
match r.Success with
| true -> Ok r.Result
| false -> Error r.Errors.[0].Message
И я мог бы написать выражение для него (гипотетически, так как я использовал их, но еще не написал свое собственное), но тогда я был бы счастлив иметь выражение asyncCloudFlareResult или даже выражение asyncCloudFlareResultOrResult, если это имеет смысл.
Мне интересно, есть ли механизм для объединения выражений, как это делает FSToolKit (хотя я подозреваю, что это просто пользовательский код).
Опять же, это вопрос о том, чтобы что-то узнать, а не о практичности, поскольку это, вероятно, добавит больше кода, чем оно того стоит.
После комментария Гаса я понял, что было бы неплохо проиллюстрировать это более простым кодом:
function DoA : int -> Async<AWSCallResult<int, string>>
function DoB : int -> Async<Result<int, string>>
AWSCallResultAndResult {
let! a = DoA 3
let! b = DoB a
return b
}
в этом примере я бы получил два типа, которые могут принимать int и возвращать строку ошибки, но они разные. У обоих есть свои выражения, поэтому я могу связать их по мере необходимости. И исходный вопрос заключается в том, как их можно объединить вместе.
ResultT
вы можете использовать для объединения некоторых CE сResult
- если эти накладные расходы стоят для вас, я не знаю конечно - person Random Dev   schedule 13.06.2021