Scheme 一元求值中的bind算子

Scheme 一元求值中的bind算子,scheme,monads,Scheme,Monads,我已经阅读了几次Scheme中的实现,我对State monad分章末尾的练习感到困扰 这篇文章很清楚,一个人通过实践获得了深刻的理解,最低限度的理论,但这个练习真的很模糊。恐怕我错过了一些重要的方面,这就是为什么我在这里问 这项工作是: 在remberevensXcountevens中,增量发生在尾部递归调用之前,但我们是自由的 重新安排这些事件的顺序。通过让续集的主体成为 第一个论点是约束状态并对续集进行适当调整。这是新的第一个论点吗 绑定一个尾部调用 它要求首先从>=操作符调用sequel

我已经阅读了几次Scheme中的实现,我对
State monad
分章末尾的练习感到困扰

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

这项工作是:

在remberevensXcountevens中,增量发生在尾部递归调用之前,但我们是自由的 重新安排这些事件的顺序。通过让续集的主体成为 第一个论点是约束状态并对续集进行适当调整。这是新的第一个论点吗 绑定一个尾部调用

它要求首先从
>=
操作符调用sequel,然后调用作为参数传递给bind的
ma

我不知道如何首先进行递归调用,然后调用改变状态值的
ma
。我只是切换了
>=
的参数,但没有切换求值顺序

如果我首先尝试评估
续集
,我不知道要传递什么

我的代码是这样的:

(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)
原始函数是

...
    (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))) 
                   (λ (_) (unit d)))))
原始函数是

...
    (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))) 
                   (λ (_) (unit d)))))

丹问我你的答案是不是很好——是的,非常好,事实上,在我看到你的答案后,我终于明白了丹的意思。谢谢。丹问我你的答案是否好——是的,非常好,事实上,在我看到你的答案后,我终于明白了丹的意思。谢谢