具有参数化元数的函数
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 是一个很好的例子,包括如何从头开始实现向量并为它们编写函数。
提醒一句,学习和使用依赖类型编程令人兴奋、令人上瘾,但也很耗时。因此,如果您想专注于手头的任务,您可能希望暂时接受 运行 时间检查。
是否可以编写 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 是一个很好的例子,包括如何从头开始实现向量并为它们编写函数。
提醒一句,学习和使用依赖类型编程令人兴奋、令人上瘾,但也很耗时。因此,如果您想专注于手头的任务,您可能希望暂时接受 运行 时间检查。