我正在使用 GHC 7.8 做一些相当有趣的事情,但遇到了一些问题。我有以下内容:
mkResultF :: Eq k => Query kvs ('KV k v) -> k -> ResultF (Reverse kvs) (Maybe v)
mkResultF Here key = ResultComp (pure . lookup key)
mkResultF q@(There p) key =
case mkResultF p key of
ResultFId a -> pure a
ResultComp c ->
ResultComp $ \foo ->
case c foo of
ResultFId a -> pure a
ResultComp c ->
ResultComp $ \foo ->
case c foo of
ResultFId a -> pure a
显然这里有一些东西需要抽象,但我不太清楚如何做到这一点。当我尝试以下操作时:
mkResultF :: Eq k => Query kvs ('KV k v) -> k -> ResultF (Reverse kvs) (Maybe v)
mkResultF Here key = ResultComp (pure . lookup key)
mkResultF q@(There p) key = magic (mkResultF p key)
magic :: ResultF (Reverse kvs) (Maybe v) -> ResultF (Reverse kvs ++ '[('KV x y)]) (Maybe v)
magic (ResultFId a) = pure a
magic (ResultComp c) = ResultComp (\foo -> magic (c foo))
这感觉像是一个“明显”的解决方案,但它没有类型检查:
Could not deduce (kvs2 ~ Reverse kvs0)
from the context (Reverse kvs ~ ('KV k v1 : kvs2))
bound by a pattern with constructor
ResultComp :: forall a k v (kvs :: [KV * *]).
([(k, v)] -> ResultF kvs a) -> ResultF ('KV k v : kvs) a,
in an equation for `magic'
at query-kv.hs:202:8-19
`kvs2' is a rigid type variable bound by
a pattern with constructor
ResultComp :: forall a k v (kvs :: [KV * *]).
([(k, v)] -> ResultF kvs a) -> ResultF ('KV k v : kvs) a,
in an equation for `magic'
at query-kv.hs:202:8
Expected type: ResultF (Reverse kvs0) (Maybe v)
Actual type: ResultF kvs2 (Maybe v)
Relevant bindings include
c :: [(k, v1)] -> ResultF kvs2 (Maybe v)
(bound at query-kv.hs:202:19)
In the first argument of `magic', namely `(c foo)'
In the expression: magic (c foo)
我真的很坚持这个。可以在此处找到包含起始代码的完整代码清单:https://gist.github.com/ocharles/669758b762b426a3f930 https://gist.github.com/ocharles/669758b762b426a3f930