代码之家  ›  专栏  ›  技术社区  ›  alinsoar

一元求值中的bind算子

  •  1
  • alinsoar  · 技术社区  · 7 年前

    我读过几次了 the article of Dan Friedman about monadic evaluation State monad .

    这篇文章很清楚,一个人通过做得到了深刻的理解,最小理论,但这个练习真的很模糊。恐怕我错过了一些重要的方面,这就是为什么我在这里问。

    练习是这样的:

    在remberevensXcountevens中,增量发生在尾部递归调用之前,但我们是自由的 重新排列这些事件。通过让续集的主体成为 rst参数绑定状态,并对续集进行适当调整。这是新的rst参数吗 将状态绑定为尾部调用?

    它要求首先从 >>= 接线员,然后呼叫 ma 作为参数传递给bind。

    我不知道如何首先进行递归调用,然后调用 妈妈 这会改变状态的值。我刚换了 >>= 但不是评价的顺序。

    如果我尝试评估 sequel 首先我不知道是什么 value 通过。

    我的代码是这样的:

    (define return
      (lambda (a)
        (lambda (s)
          (cons a s))))
    
    (define >>=
      (lambda (sequel ma)
        (lambda (s)
          (let ((pair (ma s)))
            (let ((value (car pair))
                  (state (cdr pair)))
              (let ((mb (sequel value)))
                (mb state)))))))
    
    (define rember/count
      (lambda (l)
        (cond ((null? l) (return '()))
              ((list? (car l))
               (>>= (lambda (a)
                      (>>= (lambda (d)
                             (return (cons a d)))
                           (rember/count (cdr l))))
                    (rember/count (car l))))
              ((even? (car l))
               (>>= (lambda (_) (rember/count (cdr l)))
                    ;;  here I want to evaluate the addition AFTER the `(rember/count (cdr l))`.
                    (lambda (s) (cons '_ (+ 1 s)))))
              (else
               (>>= (lambda (d)
                      (return (cons (car l) d)))
                    (rember/count (cdr l)))))))
    
    ((rember/count '(1 2 3 4 (7 8 9 10 11) 5 6)) 0)
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   mvcccccc    7 年前

    原始函数是

    ...
        (bind (λ (s) `(_ . ,(add1 s)))
                     (λ (_) (remberevensXcountevens d)))
    ...
    

    现在,首先要做的是 拥有续集的主体 ,即(rXc d), 成为要绑定的第一个参数 . 所以我们有

    (bind (remberevensXcountevens d)
          (λ (d) ...))
    

    注意,我们需要d来保持递归调用的结果。

    我们知道我们有一个偶数,我们必须在状态中加1。

    (bind (remberevensXcountevens d) 
          (λ (d) (... (λ (s) (cons '_ (add1 s))) ...)))
    

    ((s)是没有纯值的单子。我们需要绑定它,使其成为计算的一部分。 所以

    (bind (remberevensXcountevens d)
          (λ (d) (bind (λ (s) (cons '_ (add1 s))) 
                       (λ (_) ...))))
    

    现在状态更新了,我们有了一个方便的纯值。自然是这样:

    (bind (remberevensXcountevens d)
          (λ (d) (bind (λ (s) (cons '_ (add1 s))) 
                       (λ (_) (unit d)))))