我不确定标题中的“独家国家管理”事情,我尽力做到最好,试图简明扼要地解决问题。
我正在将一些我的C#代码移植到F#,试图尽可能地将其作为惯用语。我有一个实体从我的数据库中的序列请求许多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#中进行独占状态管理?
答案 0 :(得分:0)
如果您只需要初始化一组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 ()
答案 1 :(得分:0)
你可以使用state-monad(Computational Expression)。
首先我们声明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