Types 我如何创建一个;“概率”;打字拍子中的HOF(或语法)

Types 我如何创建一个;“概率”;打字拍子中的HOF(或语法),types,scheme,racket,typed-racket,Types,Scheme,Racket,Typed Racket,我正在尝试创建一个HOF类型的球拍,这将允许我表达这个想法,“在评估时,掷骰子并选择要应用的程序” 目前,我正在从事以下工作: (: odds-on ((Any * -> Any) (Any * -> Any) Real -> (Any * -> Any))) (define (odds-on choice alternative odds) (cond [(< (random) odds) choice] [else alternative])) (

我正在尝试创建一个HOF类型的球拍,这将允许我表达这个想法,“在评估时,掷骰子并选择要应用的程序”

目前,我正在从事以下工作:

(: odds-on ((Any * -> Any) (Any * -> Any) Real -> (Any * -> Any)))
(define (odds-on choice alternative odds)
  (cond [(< (random) odds) choice]
    [else alternative]))
(:赔率((任意*->任意)(任意*->任意)实数->(任意*->任意)))
(定义(选择的赔率替代赔率)
(条件[(<(随机)几率)选择]
[其他备选方案])
我的想法是我可以这样使用它:

-> ((odds-on (lambda () (displayln "hi"))
             (lambda () (displayln "bye"))
             0.75))
bye
-> ((odds-on (lambda ([x : String]) (string-append x "1"))
             (lambda ([x : String]) (string-append x "2"))
             0.23)
    "test")
- : String
"test2"
>((做一件普通事做一件稀罕事的几率为75)'x'(a b c)(集合z))

其中,
do-a-common-thing
do-a-raer-thing
在其他地方定义,并且可能具有任意的参数类型。因此,大约有3/4的时间会调用第一个函数,1/4的时间会调用第二个函数

但是我遇到了类型检查和算术问题。。。基于文档,我需要,但我不是很好地遵循文档,不是一个类型系统的学者。。。我只想能够指定两个函数和一个概率,并在运行时确定调用的函数


而且,总的来说,宏/语法形式可能是创造这种效果的更明智的方式?从接口设计的角度来看,这个功能正是我在程序中需要的,但我不知道如何用静态类型实现它。。。但是我希望静态类型有助于保持程序其他部分的句柄

我还是个新手,所以我认为这不是一个好答案

类型
(Any*->Any)
用于同质rest参数。因此,函数实际上需要接受一个rest参数,例如
(define(f.xs)…)
(lambda xs…)
。如果我相应地更改了您的示例,它会为我进行类型检查:

#lang typed/racket

(: odds-on ((Any * -> Any) (Any * -> Any) Real -> (Any * -> Any)))
(define (odds-on choice alternative odds)
  (cond [(< (random) odds) choice]
        [else alternative]))

((odds-on (lambda xs (second xs)) ;; <--
          (lambda xs (third xs))  ;; <--
          0.75)
 'x 'y 'z)
一方面,
x
是一个
过程。另一方面,
x
无法应用,因为它不是一个
过程。第三方面,我很困惑

更新:这不起作用的原因是
Procedure
是一种“不透明”类型,意思是“这个东西满足
Procedure?
但我们不知道更多的信息,因此不知道如何安全地调用它”。这就是错误消息的Zen koan“过程不是函数类型”的真正意义

Asumu的答案更好。

让我为您的示例提出一种更简单(在某些方面)的类型:

(: odds-on (All (X Y) (X Y Real -> (U X Y))))
(define (odds-on choice alternative odds) 
  (cond [(< (random) odds) choice]
        [else alternative]))
不过,这里有一点折衷,因为现在你可以在实际上没有功能的事情上通过
赔率。如果您碰巧通过了一些非函数值的
几率,您将无法调用返回值(即,类型检查器稍后将捕获它)

(注意:另一方面,如果支持键入的Racket,您将能够表示一个约束,即
X
Y
在本例中必须是函数。这可能是TR未来的工作。)

返回类型中还有
(uxy)
,您必须小心。如果在两个参数算术不兼容的函数上通过
几率,则调用结果函数将更加困难

-> ((odds-on (lambda () (displayln "hi"))
             (lambda (x) (displayln "bye"))
             0.75))
; readline-input:10:0: Type Checker: could not apply function;
;  wrong number of arguments provided
;   expected: 1
;   given: 0
;   in: ((odds-on (lambda () (displayln "hi")) (lambda (x) (displayln "bye"))
;     0.75))
; [,bt for context]

(注意:您的错误消息可能看起来有所不同。我正在运行Racket v6.0.0.4。此外,此错误消息也不太好。)

这很有帮助,但我认为问题不大。也许我需要重新编写这个问题,因为实际上,我希望函数的
几率对任意函数都有效,不管是什么类型的函数。如果可以进行类型检查那就太酷了,但至少对于程序的这一部分,我真的不在乎。。。
-> ((odds-on (lambda () (displayln "hi"))
             (lambda (x) (displayln "bye"))
             0.75))
; readline-input:10:0: Type Checker: could not apply function;
;  wrong number of arguments provided
;   expected: 1
;   given: 0
;   in: ((odds-on (lambda () (displayln "hi")) (lambda (x) (displayln "bye"))
;     0.75))
; [,bt for context]