[英]Approach to thread resources like connections in functional programming
假設您需要連接到數據庫。
因此,您將DbConnection
作為某種假設函數的最后一個參數,其類型如下: doDbStuff :: Int -> DbConnection -> Int
也許還有其他函數也依賴於DbConnection
,並且所有這些函數都在執行寫操作。 因此,它們可以單獨運行,也可以作為原子操作(即事務 )的一部分運行。
由於可能要使用一個池來管理DbConnection
,並且功能可能是原子操作的一部分,也可能不是原子操作的一部分,因此這些函數未實現從池中獲取DbConnection
實例以及將其釋放到池中的代碼。
現在,這些功能是長功能組合的一部分,某些決定可能涉及這些功能,不需要DbConnection
。 也就是說,有可能從池中獲取DbConnection
並將其用於另一個請求,這可能會產生瓶頸。
還有一種選擇,即不注入DbConnection
而是注入高階函數,如withConnection :: (DbConnection -> a) -> a
,因此每個函數都可以使用DbConnection
,使用它,整個withConnection
負責獲取和釋放連接。 這里的缺點是,作為原子操作的一部分,很難使許多功能進行協作。
目前,我一直在使用#2方法。 順便說一句,是否有任何其他方法可以保留兩種方法中的最佳方法?
JavaScript中的偽代碼:
const connectionString = '[whatever]'
const env = { connection: acquire (connectionString) }
const output = composition (arg0) (argN) (env)
// then, release the connection
// f :: a -> b -> { connection: DbConnection }
const f = x => y => ({ connection }) =>
doDbStuff (x + y) (connection)
const withConnection = f => [stuff to acquire the connection, and aftewards, release it]
const env = { withConnection }
const output = composition (arg0) (argN) (env)
// type FnConnection DbConnection c = c -> a
// f :: a -> a -> { connection: FnConnection }
const f = x => y => ({ withConnection }) =>
withConnection (doDbStuff (x + y))
有一種針對這種情況的工具,您的解決方案非常接近! 讀者adt允許您在訪問某些環境的情況下編寫函數。 這是我最喜歡的實現: https : //github.com/monet/monet.js/blob/master/docs/READER.md
不幸的是,此模式可能需要將大量代碼包裝在閱讀器類型中-但是您已經引入了withConnection包裝器,這導致幾乎相同數量的額外代碼。
這是一個示例,該示例從數據庫中讀取ID為“ 123”的文檔,覆蓋某些屬性,然后將結果寫回到數據庫中。 直到實際運行程序時才提供db連接,但是您可以編寫代碼,前提是在運行代碼時將存在db連接。
const { Reader } = require('monet');
const findById = (id) => Reader(({ db }) => db.find({ id }));
const insertDoc = (doc) => Reader(({ db }) => db.insert(doc));
const copyWithDefaults = (doc) => ({
...doc,
name: 'default name',
});
const app =
findById('123')
.map(copyWithDefaults)
.chain(insertDoc)
app.run({ db: aquire(connectionString) })
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.