Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何为内射类型函数提供输入_Haskell_Ghc - Fatal编程技术网

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

Haskell 如何为内射类型函数提供输入,haskell,ghc,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,我可以使用类型应用程序语法

在我的应用程序中,我建立了一个表达式,它的类型是某个参数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,我可以使用类型应用程序语法调用getValue$foo@'Z。这很好,但我的目的是始终使用此模式调用getValue。因此,与其让用户总是必须指定他们的表达式是相对于'Z的,我更希望这个属性是getValue中固有的,这样我就可以编写getValue foo,并可能返回2

注意:一种解决方案是使用代理:foo::Proxy d->Proxy'S d和getValue::Proxy d1->Proxy d2->Int显式地输入函数input,然后让getValue将函数应用于'Z'。这实现了我想要的,但是额外的代理很烦人。有没有一种方法不需要这个额外的代理?

将getValue重命名为getValue'并写入getValue foo=getValue'$foo@'Z

如果你的最终目标是自然数,那么这里有一个更好的具体化自然数的方法:

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

如果您愿意,您可能可以通过这种方式摆脱对代理的所有使用。

只是好奇:为什么不使用单例呢?我已经在Nat值的包装中使用了单例,所以如果您想建议一种方法,这一点也不麻烦。问题是Proxy::Proxy t,但是你想要Z::Proxy'Z-所以你自己定义一个常数就行了。如果确实必须将此工作移到getValue,则可以使用实例重叠将自由类型变量实例化为'Z',但这确实不值得。@user2407038不确定问题的意思是Proxy::Proxy t。如果我使用类型应用程序,则无需定义任何值。@crockeea如果foo的类型是Proxy s Z,则不会有问题。因此,通过将其定义为op-op-Proxy::Proxy'Z而不是op-op-Proxy::Proxy t,为其指定此类型。那么,大概你不想在任何地方都指定类型,所以你定义了一个常量_Z::Proxy'Z来节省你的键入时间。我想你的第一行不可能工作,是吗?我们必须告诉编译器getValues参数可以接受类型应用程序。getValue的类型是什么?这里的重点不是反映Nat的值,这只是一个示例。关键是在调用getValue时自动向类型函数提供输入。如果你的第一种方法真的可以编译,那么你的问题似乎是一个更一般的例子,如何使fxy总是使用一些特定的y,而不是把它作为一个参数?答案是使函数f'x=fx固定。您可能必须添加一个显式forall:getValue'::forall n::Nat。Int。您只需将类型参数从值级代理lambda移到类型级大写lambda即可。@Lazersmoke注意getValue foo不会编译。我认为这个答案没有抓住问题的关键——你提议的getValue签名没有帮助。福尔p。代理p抹杀了恢复foo至少两种性质的任何希望。我认为这个问题的真正答案是这是不可能的。
getValue :: forall n. ReifyNat n => Integer
getValue = reifyNat