具有参数化元数的函数

Functions with parametrised arity

是否可以编写 returns 其签名取决于构建器函数参数的函数?

具体来说,我正在改进我编写的原始递归的实现。我想要类似工厂的函数,为数字参数生成一个函数,该函数适用于长度等于为数字参数传递的参数的元组或列表。目前我正在处理像 pr 1 2 [0,5,13] 这样的情况,从原始递归的角度来看,这是一个无效的语句,在运行时通过 Either:

pr :: (Show a) => Int -> Int -> [a] -> Either String a
pr i k args
  | 1 <= i && i <= k && length args == k = Right $ args!!(i-1)
  | i <= 0 = Left "first argument of pr needs to be greater or equal to 1"
  | k < i = Left "first argument of pr needs to be lesser or equal to the second argument"
  | length args /= k = Left $ "pr expected "++(show k)++" arguments, got "++(show $ length args)++": pr "++(concat[show i, " ", show k, " ", show args])

但我想以某种方式在编译时捕捉到这种情况,因为从我想用它实现的正式系统的角度来看,这是一个编译时错误——传递给函数的参数多于它的域指定。

这在某种程度上是否可能,如果不可能,对于应该是无效语句的编译时错误,正确的方法是什么。

你想要的是一个大小的向量。它就像一个列表,但除了其元素的类型之外,它还按类型级别的自然数进行参数化。

sized-vector Hackage 上的软件包就是您所需要的。碰巧,您要实现的函数是此库中的 last 函数。

请注意,每次调用 last 时,您都必须向编译器证明其参数向量的大小至少为 1。您可以通过在源代码中构建向量(例如,编译器将理解 1 :- 2 :- Nil 的大小为 2),或者如果向量是在 运行 时通过从列表转换获得的,则您必须编写一个函数来给出 运行 如果它没有元素或构造一个大小至少为 1 的向量,即对于某些 n.

具有类型级别大小 S n,则出现时间错误

如果您不熟悉依赖类型编程(包括这个以及更多的范例),我建议您先阅读一些教程。例如,this post 是一个很好的例子,包括如何从头开始实现向量并为它们编写函数。

提醒一句,学习和使用依赖类型编程令人兴奋、令人上瘾,但也很耗时。因此,如果您想专注于手头的任务,您可能希望暂时接受 运行 时间检查。