是否可以 'uncurry' 一个 forall 量词?
Is it possible to 'uncurry' a forall quantifier?
假设我们有一个类型构造函数 f,它通过 DataKinds 提升的对接受两种类型。
forall (f :: (ka, kb) -> *)
然后我可以实现一个函数 forward
,它类似于 forall
量词的 curry
:
forward :: forall (f :: (ka, kb) -> *).
(forall (ab :: (ka, kb)). f ab) ->
(forall (a :: ka) (b :: kb). f '(a, b))
forward x = x
但是反向函数有问题:
backward :: forall (f :: (*, *) -> *).
(forall (a :: *) (b :: *). f '(a, b)) ->
(forall (ab :: (*, *)). f ab)
backward x = x
GHC 8.0.1 给出错误信息:
• Couldn't match type ‘ab’ with ‘'(a0, b0)’
‘ab’ is a rigid type variable bound by
the type signature for:
backward :: forall (ab :: (*, *)). (forall a b. f '(a, b)) -> f ab
at :6:116
Expected type: f ab
Actual type: f '(a0, b0)
• In the expression: x
In an equation for ‘backward’: backward x = x
从概念上讲,这似乎是一个有效的程序。还有其他方法可以实现这个功能吗?或者这是 GHC 的已知限制?
正如 pigworker 和 Daniel Wagner 指出的那样,问题在于 ab
可能是 "stuck type"。您有时可以使用类型族来解决这个问题(正如我在 one of pigworker's papers 中学到的):
type family Fst (x :: (k1, k2)) :: k1 where
Fst '(t1, t2) = t1
type family Snd (x :: (k1, k2)) :: k2 where
Snd '(t1, t2) = t2
backward :: forall (f :: (*, *) -> *) (ab :: (*, *)) proxy .
proxy ab ->
(forall (a :: *) (b :: *). f '(a, b)) ->
f '(Fst ab, Snd ab)
backward _ x = x
有时,另一种选择是使用包装器。
newtype Curry f x y = Curry (f '(x,y))
data Uncurry f xy where
Uncurry :: f x y -> f '(x, y)
假设我们有一个类型构造函数 f,它通过 DataKinds 提升的对接受两种类型。
forall (f :: (ka, kb) -> *)
然后我可以实现一个函数 forward
,它类似于 forall
量词的 curry
:
forward :: forall (f :: (ka, kb) -> *).
(forall (ab :: (ka, kb)). f ab) ->
(forall (a :: ka) (b :: kb). f '(a, b))
forward x = x
但是反向函数有问题:
backward :: forall (f :: (*, *) -> *).
(forall (a :: *) (b :: *). f '(a, b)) ->
(forall (ab :: (*, *)). f ab)
backward x = x
GHC 8.0.1 给出错误信息:
• Couldn't match type ‘ab’ with ‘'(a0, b0)’ ‘ab’ is a rigid type variable bound by the type signature for: backward :: forall (ab :: (*, *)). (forall a b. f '(a, b)) -> f ab at :6:116 Expected type: f ab Actual type: f '(a0, b0) • In the expression: x In an equation for ‘backward’: backward x = x
从概念上讲,这似乎是一个有效的程序。还有其他方法可以实现这个功能吗?或者这是 GHC 的已知限制?
正如 pigworker 和 Daniel Wagner 指出的那样,问题在于 ab
可能是 "stuck type"。您有时可以使用类型族来解决这个问题(正如我在 one of pigworker's papers 中学到的):
type family Fst (x :: (k1, k2)) :: k1 where
Fst '(t1, t2) = t1
type family Snd (x :: (k1, k2)) :: k2 where
Snd '(t1, t2) = t2
backward :: forall (f :: (*, *) -> *) (ab :: (*, *)) proxy .
proxy ab ->
(forall (a :: *) (b :: *). f '(a, b)) ->
f '(Fst ab, Snd ab)
backward _ x = x
有时,另一种选择是使用包装器。
newtype Curry f x y = Curry (f '(x,y))
data Uncurry f xy where
Uncurry :: f x y -> f '(x, y)