Lisp 是否可以通过映射函数和lambda使类型化的Racket推断类型?
在my to中,我发现您似乎经常需要向用作映射函数参数的匿名函数的参数添加类型注释:Lisp 是否可以通过映射函数和lambda使类型化的Racket推断类型?,lisp,racket,typed-racket,Lisp,Racket,Typed Racket,在my to中,我发现您似乎经常需要向用作映射函数参数的匿名函数的参数添加类型注释:map、foldl等等 这里有两个简单的例子(所有这些都假设#lang typed/racket,我使用的是racket8.0) 我希望这个能起作用: (define (f (l : (Listof Number))) : (Listof Number) (map (λ (x) (+ x 1)) l)) 但事实并非如此:你需要告诉它,x的参数是一个数字: (define
map
、foldl
等等
这里有两个简单的例子(所有这些都假设#lang typed/racket
,我使用的是racket8.0)
我希望这个能起作用:
(define (f (l : (Listof Number)))
: (Listof Number)
(map (λ (x)
(+ x 1))
l))
但事实并非如此:你需要告诉它,x
的参数是一个数字
:
(define (f (l : (Listof Number)))
: (Listof Number)
(map (λ ((x : Number))
(+ x 1))
l))
或者您可以使用for/list
,现在不需要注释:
(define (f (l : (Listof Number)))
: (Listof Number)
(for/list ([x (in-list l)])
(+ x 1)))
另一方面,这将起作用:
(define (g (l : (Listof Number)))
: Number
(foldl + 0 l))
但若我将其替换为(有点傻,但我想要一个小例子)
它失败了,需要转化为
(define (g (l : (Listof Number)))
: Number
(foldl (λ ((x : Number) (y : Number)) (+ x y)) 0 l))
只有当匿名函数作为参数传递时才会发生这种情况,正如我所看到的,因为这个(同样愚蠢的)函数是OK的:
(define (gg (x : Number) (y : Number))
((λ (a b) (+ a b))
x y))
在最后一个函数中,您可以从GUI中看到,它已成功地从x
和y
的类型推断出a
和b
的类型
很可能我只是对这里的一些事情感到困惑,然而,我甚至连打字的能力都没有
所以问题是:我是不是很困惑,这些匿名函数的参数类型真的不可知,还是只是类型检查器(还)不够聪明,无法自行推断?我不确定你所说的“不可知”是什么意思,但这确实是类型化Racket的工作原理。如果应用多态函数,它不会使用参数的类型来推断其他参数的类型。但它确实使用参数的类型来推断上一个示例中的参数类型。好的,谢谢。我猜类型系统要想推断出对人类来说显而易见的东西还有很长的路要走(尽管CMUCL/SBCL在这种情况下可以做有用的事情,尽管它可能通过黑客来做)。我认为更多的是关于类型系统如何工作,而不是它是否使用黑客——Haskell会推断出这一点,因为它使用了非常不同的算法和方法。
(define (gg (x : Number) (y : Number))
((λ (a b) (+ a b))
x y))