【问题标题】:How do I create a "probability" HOF (or syntax) in typed racket如何在打字球拍中创建“概率”HOF(或语法)
【发布时间】:2014-04-29 11:52:31
【问题描述】:

我正在尝试在打字球拍中创建一个 HOF,这将使我能够表达这个想法,“在评估时,掷骰子并选择要应用的程序”。

目前,我正在处理以下内容:

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

我的想法是我可以这样使用它:

&gt; ((odds-on do-a-common-thing do-a-rarer-thing .75) 'x '(a b c) (set z))

其中do-a-common-thingdo-a-rarer-thing 在别处定义,并且可能具有任意参数数量和类型。这样大约 3/4 的时间会调用第一个函数,而 1/4 的时间会调用第二个函数。

但是我左右都遇到了类型检查和 arity 问题...根据文档,我需要 heterogenous rest arguments,但我没有很好地遵循文档,不是类型系统的学者...我只是希望能够指定两个函数和一个概率,并在运行时确定调用的函数!

而且,总的来说,也许宏/语法形式会是一种更明智的方式来创建这种效果?从界面设计的角度来看,这种能力正是我在程序中所需要的,但我不知道如何用静态类型来实现它......但我希望静态类型能够帮助处理程序的其他部分.

【问题讨论】:

    标签: types scheme racket typed-racket


    【解决方案1】:

    我还是 Typed Racket 的新手,所以我认为这不是一个很好的答案。

    (Any * -&gt; Any) 类型用于同质剩余参数。所以这个函数实际上需要一个 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)
    

    当然,您可能并不真的希望函数采用像 xs 这样的休息参数,而不是像 x y z 这样的普通参数。您可能仅在尝试查找将进行类型检查的 something 时使用 rest 参数。在那种情况下,我不知道该告诉你什么(还)。


    更新:根据您的评论,我对此进行了另一次破解,使用 Procedure 类型,但结果不是很好。

    #lang typed/racket
    
    (: odds-on (Procedure Procedure Real -> Procedure))
    (define (odds-on choice alternative odds)
      (cond [(< (random) odds) choice]
            [else alternative]))
    
    (define x (odds-on (lambda () #t)
                       (lambda () #f)
                       0.75))
    
    x
    ; - : Procedure
    ; #<procedure:/tmp/tr.rkt:9:10>
    
    (x)
    ; stdin::12271: Type Checker: Cannot apply expression of type Procedure, since it is not a function type
    ;   in: (x)
    

    一方面,x Procedure。另一方面,x 不能应用,因为它不是 Procedure。另一方面,我很困惑。

    更新:这不起作用的原因是 Procedure 是一种“不透明”类型,这意味着“这件事满足 procedure? 但我们不会知道更多信息——因此不要知道如何安全地调用它”。这就是错误消息中的 Zen koan,“过程不是函数类型”的意义。

    阿苏姆的回答更好。

    【讨论】:

    • 这很有帮助,但我认为问题不大。也许我需要重新编写这个问题,因为真的,我希望 odds-on 函数适用于任何数量和类型的任意函数。如果可以对其进行类型检查会很酷,但至少对于程序的那一部分我并不关心......
    【解决方案2】:

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

    (: odds-on (All (X Y) (X Y Real -> (U X Y))))
    (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"
    

    这里有一点折衷,因为现在你可以传递odds-on 那些实际上不是函数的东西。如果您碰巧传递了odds-on 一些非函数值,您将无法调用返回的值(即,无论如何,类型检查器都会在稍后捕获它)。

    (注意:顺便说一句,如果 Typed Racket 支持bounded polymorphism,您将能够表达XY 在此示例中必须是函数的约束。这可能是TR 未来的工作。)

    返回类型中还有(U X Y),您必须小心。如果您传递 odds-on 两个参数不兼容的函数,则调用结果函数将更加困难。

    -> ((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。此外,此错误消息不是那么好。)

    【讨论】:

      猜你喜欢
      • 2021-04-01
      • 2019-01-12
      • 2020-02-12
      • 2022-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-08
      相关资源
      最近更新 更多