我目前正在教自己F#,并且已经遇到过这种需求几次,所以我认为是时候回答。
基本上我希望一个函数是通用的,并且可以处理除
type CacheStore = System.Collections.Concurrent.ConcurrentDictionary<Guid * obj, DateTime * obj>
let (|ItemPresent|ItemExpired|ItemNotPresent|) ((cacheStore : CacheStore), cacheKey) =
if cacheStore.ContainsKey cacheKey
then
let expiryTime, value = cacheStore.[cacheKey]
if expiryTime > DateTime.Now
then ItemPresent value
else ItemExpired (DateTime.Now - expiryTime)
else ItemNotPresent
let cache<'a, 'b> (cacheStore : CacheStore) (functionToCache : 'a -> 'b) =
let functionId = Guid.NewGuid()
let updateCache (cacheStore : CacheStore) cacheKey newValue =
printfn "Updating cache"
cacheStore.[cacheKey] <- ((DateTime.Now.AddSeconds 1.0), box newValue)
newValue
fun arg ->
let cacheKey = functionId, (box arg)
match cacheStore, cacheKey with
| ItemPresent value ->
printfn "Retrieving from cache"
value :?> 'b
| ItemExpired ago ->
printfn "Item in cache but expired %A ago; running function" ago
updateCache cacheStore cacheKey (functionToCache arg)
| ItemNotPresent ->
printfn "Item not in cache; running function."
updateCache cacheStore cacheKey (functionToCache arg)
显然,缓存一个void / return unit,的函数是没有意义的,事实上如果有人试图缓存一个&#39; a - &gt;这个代码将在运行时失败。单位功能。
如果有人不正确地调用它,如何在编译时使其失败?从我所读过的内容来看,我觉得我应该能够通过内联函数和静态类型约束来实现这一点,但我不知道如何编写它......
更新 我后来发现这个特定的版本实际上 使用单元函数 - 缓存包装器基本上没有效果(它只是增加了运行时开销),但原始问题的要点仍然存在:我可以停止人们用单位函数调用这个函数?
答案 0 :(得分:3)
没有好办法做到这一点,我建议不要尝试。 unit
只是一个具有单个值(()
)的类型 - 为什么要以任何特殊方式处理这一类型?当与unit
返回功能一起使用时,您的功能不会中断,那么为什么不相信您的呼叫者如果不提供任何好处就不使用它?如果您的调用者试图以通用方式使用您的函数,那么您对函数的任何限制都将传播给它们,这也可能是不受欢迎的。