在我的应用程序中,我构建了一个表达式,其类型是某个参数d
的(单射)函数。例如:
op :: Proxy d -> Proxy ('S d)
op _ = Proxy
foo :: forall d . Proxy ('S ('S d))
foo = op $ op Proxy
在我建立了像foo
这样的表达式之后,我想解释一下:
getValue :: Proxy (d :: Nat) -> Int
getValue _ = ...
要解释foo
,我可以使用type-applications语法调用getValue $ foo @'Z
。这很好,除了我的意图是总是用这种模式调用getValue
。因此,不是让用户始终必须指定他们的表达式相对于'Z
,如果此属性是getValue
中固有的,那么我更喜欢它,所以我可以写getValue foo
并且可能会回来2
。
注意:一种解决方案是使用Proxy
:foo :: Proxy d -> Proxy ('S ('S d))
和getValue :: (Proxy d1 -> Proxy d2) -> Int
明确输入函数输入,然后让getValue
将函数应用于{ {1}}。这实现了我想要的,但额外的'Z
很烦人。有没有一种方法不需要额外的Proxy
?
答案 0 :(得分:-2)
将您的getValue
重命名为getValue'
并撰写getValue foo = getValue' $ foo @'Z
。
getValue :: (forall (d :: Nat). Proxy d) -> Int
getValue foo = getValue' $ foo @'Z
getValue' :: Proxy (d :: Nat) -> Int
getValue' Proxy = ...
如果这是你的最终目标,那么这是一种更好的自然数字表达方式:
class ReifyNat (n :: Nat) where
reifyNat :: Integer
instance ReifyNat 'Z where
reifyNat = 0
instance ReifyNat n => ReifyNat ('S n) where
reifyNat = succ (reifyNat @n)
getValue :: forall n. ReifyNat n => Proxy n -> Integer
getValue _ = reifyNat @n
或者只是使用:
getValue :: forall n. ReifyNat n => Integer
getValue = reifyNat
如果您愿意,您可以以这种方式摆脱所有对Proxy
的使用。