这是一个关于 Haskell 中 Data.Reflection 的类型问题。反射让我接受一个 Int 并将其转换为一种类型。
下面的函数 f 和 g 是我们对合理事物的最佳尝试,如果您有更好的方法,让我们拥有它!
例如,我可以通过执行以下操作添加数字 mod 41:
import Data.Reflection
import Data.Proxy
newtype Zq q i = Zq i deriving (Eq)
instance (Reifies q i, Integral i) => Num (Zq q i) where
(...)
zqToIntegral :: (Reifies q i, Integral i) => Zq q i -> i
(...)
f :: forall i . (Integral i) => i -> (forall q . Reifies q i => Zq q i) -> i
f modulus k =
reify modulus (\ (_::Proxy t) -> zqToIntegral (k :: Zq t i)
然后
>>:t (f 41 (31+15))
(f 41 (31+15)) :: Integral i => i
但是,我们想编写如下函数:
g :: forall i . (Integral i) => i -> (forall q . Reifies q i => Zq q i) -> Zq q i
g modulus k =
reifyIntegral modulus (\ (_::Proxy t) -> (k :: Zq t i)
并想得到:
>>:t (g 41 (31+15))
(g 41 (31+15)) :: <some type info> => Zq q i
不同之处在于我们希望能够返回一个使用 reified int 的类型。上述定义的至少一个问题是 rank-2 类型 q 对返回类型不可见。
Data.Reflection 中 reify 的签名是
reify :: a -> (forall s. Reifies s a => Proxy s -> r) -> r
据我们所知,这需要 rank-2 类型,并且我们不知道(如果确实可能)如何将此类型公开给函数的返回类型。