タイトルの「排他的状態管理」についてはよくわかりませんが、問題を簡潔に表現するために最善を尽くして作成しました。
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 Manager の新しいコピーが作成されると、古いコピーの使用を止めて同じ ID を再び取得する力がなくなることです。
では、F# で排他的な状態管理を行うにはどうすればよいでしょうか。