Не совсем уверен, что заголовок описывает это нормально, но у меня есть примерно следующий код:
пакет.зависимости:
source https://www.nuget.org/api/v2
nuget fsharpx.extras
nuget mongodb.driver
некоторые.fsx:
#r @".\packages\MongoDB.Bson\lib\net45\MongoDB.Bson.dll"
#r @".\packages\MongoDB.Driver\lib\net45\MongoDB.Driver.dll"
#r @".\packages\MongoDB.Driver.Core\lib\net45\MongoDB.Driver.Core.dll"
#r @".\packages\FSharpX.Extras\lib\net45\FSharpX.Extras.dll"
open MongoDB
open MongoDB.Driver
open MongoDB.Bson
open MongoDB.Bson.Serialization
open FSharpx.Choice
let private createClient (connectString:string) = MongoClient(connectString)
let CreateClient = protect createClient
let private getDb name (client:IMongoClient) = client.GetDatabase(name)
let GetDB1 name client =
choose {
let! c = client
return! (protect (getDb name) c)
}
let GetDB2 name (client:Choice<IMongoClient, exn>) =
protect (getDb name)
<!> client
Смысл этого «упражнения» заключался в том, чтобы написать GetDB2 так, чтобы он делал то же самое, что и GetDB1, но использовал операторы (аппликативы?), но в данный момент я не могу повернуть голову, чтобы справиться с этим.
Приведенный выше код компилируется, но подписи для GetDB1 и GetDB2 не равны, и я явно делаю что-то неправильно.
val GetDB1 :
name:string ->
client:Choice<#MongoDB.Driver.IMongoClient,exn> ->
Choice<MongoDB.Driver.IMongoDatabase,exn>
val GetDB2 :
name:string ->
client:Choice<MongoDB.Driver.IMongoClient,exn> ->
Choice<Choice<MongoDB.Driver.IMongoDatabase,exn>,exn>
Я пробовал несколько версий и порядков действий в GetDB2, но я более или менее всегда заканчивался той же сигнатурой, что и выше.
Общая идея, которая у меня изначально была, заключалась в том, чтобы написать небольшую функцию, выполняющую то, что она должна делать, а затем добавить обработку исключений (защитить), а затем "обернуть" и "развернуть" соответственно.
Это, конечно, тоже может быть не совсем правильной идеей.
Может ли кто-нибудь указать мне некоторые направления для дальнейшего изучения, примеры кода или что-то еще? Любые комментарии любого типа на самом деле приветствуются на этом этапе ;-)
Дополнение
Я думаю, что следующее должно быть примерно таким же, как указано выше, но без зависимостей mongodb.
#r @".\packages\FSharpX.Extras\lib\net45\FSharpX.Extras.dll"
type DataBase =
{
Name: string
}
type Client =
{
connectString: string
} with member this.GetDatabase name = {
Name = name
}
open FSharpx.Choice
let private createClient (connectString:string) = {
connectString= connectString
}
let CreateClient = protect createClient
let private getDb name (client:Client) = client.GetDatabase name
let GetDB1 name client =
choose {
let! c = client
return! (protect (getDb name) c)
}
let GetDB2 name client =
protect (getDb name)
<!> client
<!>
часто используется вместо<$>
в Haskell, который не является допустимым оператором в F#. Это просто инфиксная версияmap
(fmap
в Haskell). - person Mark Seemann   schedule 18.11.2016Applicative
определяется<*>
иpure
. AFAICT, в FSharpx.Choice это<*>
иreturnM
. - person Mark Seemann   schedule 18.11.2016(=<<)
вместо(<!>)
. - person kvb   schedule 18.11.2016>>=
— это «просто» стандартный оператор bind, который вместе сreturn
/pure
определяет монаду. В выражениях вычислений F# привязкиlet!
преобразуются вBind
а>. - person Mark Seemann   schedule 18.11.2016