[英]How can I manage an exclusive state in F#?
我不確定標題中是否包含“專有狀態管理”,我竭盡所能,力圖簡潔地解決問題。
我正在將我的一些C#代碼移植到F#,以盡我所能地做到這一點。 我有一個實體,該實體從數據庫中的序列中請求多個ID,然后將這些ID分配給需要的任何人。 給出ID后,該ID將不再對其他任何人可用。 因此,必須有某種與該實體相關聯的狀態來跟蹤ID的剩余數量。 由於使用可變狀態不是慣用語言,因此我可以做這樣的事情:
let createIdManager =
let idToStartWith = 127
let allowed = 10
let givenOut = 0
(idToStartWith, allowed, givenOut)
-
let getNextAvailableId (idToStartWith, allowed, givenOut) =
if givenOut< allowed
then ((idToStartWith, allowed, givenOut+ 1), Some(idToStartWith + givenOut))
else ((idToStartWith, allowed, givenOut), None)
let (idManager, idOpt) = getNextAvailableId createIdManager()
match idOpt with
| Some(id) -> printf "Yay!"
| None -> reloadIdManager idManager |> getNextAvailableId
這種方法是慣用的(據我所知),但是非常脆弱。 有很多方法可以弄亂它。 我最大的擔心是,一旦提供了一個ID並創建了ID管理器的較新副本,便無法阻止您使用較舊的副本並再次獲得相同的ID。
那么,我該如何在F#中進行排他狀態管理呢?
如果您只需要初始化一次ID集,則只需在本地函數作用域內隱藏對列表的可變引用,如下所示:
let nextId =
let idsRef = ref <| loadIdsFromDatabase()
fun () ->
match idsRef.Value with
| [] ->
None
| id::ids ->
idsRef := ids
Some id
let id1 = nextId ()
let id2 = nextId ()
您可以使用state-monad(計算表達式)。
首先我們聲明狀態單子
type State<'s,'a> = State of ('s -> 'a * 's)
type StateBuilder<'s>() =
member x.Return v : State<'s,_> = State(fun s -> v,s)
member x.Bind(State v, f) : State<'s,_> =
State(fun s ->
let (a,s) = v s
let (State v') = f a
v' s)
let withState<'s> = StateBuilder<'s>()
let runState (State f) init = f init
然后,我們定義您的“ IdManager”和一個函數,以在執行函數后獲取下一個可用的ID以及新狀態。
type IdManager = {
IdToStartWith : int
Allowed : int
GivenOut : int
}
let getNextId state =
if state.Allowed > state.GivenOut then
Some (state.IdToStartWith + state.GivenOut), { state with GivenOut = state.GivenOut + 1 }
else
None, state
最后,我們定義請求id並執行state-monad的邏輯。
let idStateProcess =
withState {
let! id1 = State(getNextId)
printfn "Got id %A" id1
let! id2 = State(getNextId)
printfn "Got id %A" id2
//...
return ()
}
let initState = { IdToStartWith = 127; Allowed = 10; GivenOut = 0 }
let (_, postState) =
runState
idStateProcess
initState //This should be loaded from database in your case
輸出:
Got id Some 127
Got id Some 128
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.