我正在尝试实现一个透明缓存,可以在特定对象不可用时加载它,或者返回一个已由(name
)索引的已存在对象。
我试过这个:
loader' objs name = case findObj objs name of
Nothing → (new_obj, loader' new_objs)
Just obj → (obj, loader' objs)
where
new_objs = [(name, new_obj)] ++ objs
new_obj = readObj name
loader = loader' []
但我得到了
Occurs check: cannot construct the infinite type: t = (ObjType, String -> t)
看起来完全像我想要的东西:)
如何修复函数以便编译?
澄清:
根据要求,签名(findObj返回通过键找到的已知值,或者Nothing,readObj为键创建新的obj):
findObj :: [(String, ObjType)] -> String -> Maybe ObjType
readObj :: String -> ObjType
是的 - 我需要一个缓存,因为密钥是文件名,每次需要某个对象时我都不想读取+解析文件。
答案 0 :(得分:2)
为什么不只是memoize findObj?
答案 1 :(得分:2)
两个想法(疯狂的猜测?)看起来好像它未能在Just obj
子句和/或readObj name
中产生正确的类型签名,尝试类似的东西可能会很有趣这样:
loader' :: [(String, ObjType)] -> String -> (ObjType, String -> ObjType)
loader' objs name = case findObj objs name of
Nothing → (new_obj, loader' new_objs) where
new_objs = [(name, new_obj)] ++ objs
new_obj = readObj name
Just obj → (obj, loader' objs)
loader = loader' []
我不是说这会解决它(但我想它可能会);相反,我说它可能会将问题转化为更有意义的问题,或以其他方式阐明情况。
编辑:
应用Tom Lokhorst关于命名缓存类型的建议引导我们:
type Cache = [(String, ObjType)]
loader' :: Cache -> String -> (ObjType, ????)
loader' objs name = case findObj objs name of
Nothing → (new_obj, loader' new_objs) where
new_objs = [(name, new_obj)] ++ objs
new_obj = readObj name
Just obj → (obj, loader' objs)
loader = loader' []
这使问题显而易见。 loader'的第二个结果的类型是一个函数,它接受一个字符串,产生一个由ObjType组成的函数和一个函数,它接受一个字符串,产生一个由ObjType组成的函数和一个函数,它接受一个字符串并产生一对由一个ObjType和一个带字符串的函数组成,它产生一个由ObjType组成的对......你得到了图片。
如果你这样重写:
type Cache = [(String, ObjType)]
loader' :: Cache -> String -> (ObjType, Cache)
loader' objs name = case findObj objs name of
Nothing → (new_obj, new_objs) where
new_objs = [(name, new_obj)] ++ objs
new_obj = readObj name
Just obj → (obj, objs)
它应该编译,但你必须改变你的使用方式。
答案 2 :(得分:2)
Haskell不支持这样的类型:
type t = Int -> t
这是因为编译器尝试展开此类型,以键入检查它。由于类型系统是quit strict,因此在类型检查期间会导致无限循环。现在拥有一个比你能做到的更懒惰的类型系统会更好,但是,目前还没有Haskell。
然而,正如MarkusQ所说,更容易改变loader'
函数的作用。我想我会这样写:
type Cache = [(String, ObjType)]
loader' :: Cache -> String -> (ObjType, Cache)
这是一个获取缓存和搜索字符串的函数,返回答案和(可能更新的)缓存。
答案 3 :(得分:0)
您可能希望查看haskell中的this implementation缓存。