如何为内射型函数提供输入

时间:2017-04-04 18:57:12

标签: haskell ghc

在我的应用程序中,我构建了一个表达式,其类型是某个参数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

注意:一种解决方案是使用Proxyfoo :: Proxy d -> Proxy ('S ('S d))getValue :: (Proxy d1 -> Proxy d2) -> Int明确输入函数输入,然后让getValue将函数应用于{ {1}}。这实现了我想要的,但额外的'Z很烦人。有没有一种方法不需要额外的Proxy

1 个答案:

答案 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的使用。