简体   繁体   English

使用Ada子类型等功能语言定义自然数

[英]Define natural numbers in functional languages like Ada subtypes

In Ada to define natural numbers you can write this: 在Ada中定义自然数,您可以这样写:

subtype Natural  is Integer range 0 .. Integer'Last;

This is type-safe and it is checked at compile-time. 这是类型安全的,并在编译时检查。 It is simple (one-line of code) and efficient (it does not use recursion to define natural numbers as many functional languages do). 它简单(一行代码)且效率高(它不像许多功能语言那样使用递归来定义自然数)。 Is there any functional language that can provide similar functionality? 有没有可以提供类似功能的功能语言?

Thanks 谢谢

This is type-safe and it is checked at compile-time. 这是类型安全的,并在编译时检查。

As you already pointed out in the comments to your question, it is not checked at compile time. 正如您在问题注释中已经指出的那样,在编译时不会对其进行检查。 Neither is equivalent functionality in Modula-2 or any other production-ready, general-purpose programming language. Modula-2或任何其他可用于生产的通用编程语言都没有等效功能。

The ability to check constraints like this at compile time is something that requires dependent types, refinement types or similar constructs. 在编译时检查此类约束的能力需要某种依赖类型,细化类型或类似构造。 You can find those kinds of features in theorem provers like Coq or Agda or in experimental/academic languages like ATS or Liquid Haskell . 您可以在定理证明者(如CoqAgda)或实验/学术语言(如ATSLiquid Haskell)中找到这类功能。

Now of those languages I mentioned Coq and Agda define their Nat types recursively, so that's not what you want, and ATS is an imperative language. 现在,我提到了Coq和Agda这些语言,它们递归地定义了它们的Nat类型,所以这不是您想要的,并且ATS是命令式语言。 So that leaves Liquid Haskell (plus languages that I didn't mention, of course). 这样就留下了Liquid Haskell(当然还有其他我没有提到的语言)。 Liquid Haskell is Haskell with extra type annotations, so it's definitely a functional language. Liquid Haskell是具有额外类型注释的Haskell,因此它绝对是一种功能语言。 In Liquid Haskell you can define a MyNat (a type named Nat is already defined in the standard library) type like this: 在Liquid Haskell中,您可以定义一个MyNat类型(标准库中已经定义了一个名为Nat的类型),如下所示:

{-@ type MyNat = {n:Integer | n >= 0} @-}

And then use it like this: 然后像这样使用它:

{-@ fac :: MyNat -> MyNat @-}
fac :: Integer -> Integer
fac 0 = 1
fac n = n * fac (n-1)

If you then try to call fac with a negative number as the argument, you'll get a compilation error. 如果然后尝试使用负数作为参数调用fac ,则会收到编译错误。 You will also get a compilation error if you call it with user input as the argument unless you specifically check that the input was non-negative. 如果您以用户输入作为参数调用它,也将出现编译错误,除非您专门检查输入是否为非负数。 You would also get a compilation error if you removed the fac 0 = 1 line because now n on the next line could be 0, making n-1 negative when you call fac (n-1) , so the compiler would reject that. 如果删除fac 0 = 1行,也会导致编译错误,因为现在下一行的n可能为0,因此在调用fac (n-1)n-1负,因此编译器将拒绝该错误。

It should be noted that even with state-of-the-art type inference techniques non-trivial programs in languages like this will end up having quite complicated type signatures and you'll spend a lot of time and effort chasing type errors through an increasingly complex jungle of type signatures having only incomprehensible type errors to guide you. 应该指出的是,即使使用最新的类型推断技术,像这样的语言中的非平凡程序最终也将具有非常复杂的类型签名,并且您将花费大量的时间和精力通过越来越多的类型来追逐类型错误类型签名的复杂丛林,只有难以理解的类型错误才能指导您。 So there's a price for the safety that features like these offer you. 因此,这些功能可以为您提供安全的价格。 It should also be pointed out that, in a Turing complete language, you will occasionally have to write runtime checks for cases that you know can't happen as the compiler can't prove everything even when you think it should. 还应该指出,在使用图灵完整的语言的情况下,您有时必须编写运行时检查,以了解无法发生的情况,因为即使您认为应该编译器也无法证明所有内容。

Typed Racket, a typed dialect of Racket , has a rich set of numeric subtypes and it knows about a fair number of closure properties (eg, the sum of two nonnegative numbers is nonnegative, the sum of two exact integers is an exact integer, etc). 类型化的球拍,一个类型的话球拍 ,有着丰富的数字亚型,它知道了相当多的封闭性(例如,两个非负数的和非负,双精确整数的和是一个准确的整数,等)。 Here's a simple example: 这是一个简单的例子:

#lang typed/racket
(: f : (Nonnegative-Integer Nonnegative-Integer -> Positive-Integer))
(define (f x y)
  (+ x y 1))

Type checking is done statically, but of course the typechecker is not able to prove every true fact about numeric subtypes. 类型检查是静态完成的,但是类型检查器当然不能证明有关数字子类型的所有真实事实。 For example, the following function in fact only returns values of type Nonnegative-Integer , but the type rules for subtraction only allow TR to conclude the result type of Integer . 例如,以下函数实际上仅返回类型为Nonnegative-Integer值,但是减法的类型规则仅允许TR得出Integer的结果类型。

> (lambda: ([x : Nonnegative-Integer] [y : Nonnegative-Integer])
    (- x (- x y)))
- : (Nonnegative-Integer Nonnegative-Integer -> Integer)
#<procedure>

The Typed Racket approach to numbers is described in Typing the Numeric Tower by St-Amour et al (appeared at PADL 2012). St-Amour等人(在PADL 2012中出现)在“ 键入数字塔”中描述了数字的类型化拍子方法。 There's usually a link to the paper here , but the link seems to be broken at the moment. 有通常的文件的链接在这里 ,但链接似乎在瞬间被打破。 Google has a cached rendering of the PDF as HTML, if you search for the title. 如果您搜索标题,Google会将PDF缓存为HTML。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM