gpt4 book ai didi

haskell - 如何在使用惰性序列时观察进度?

转载 作者:行者123 更新时间:2023-12-04 23:50:04 25 4
gpt4 key购买 nike

我想知道以下在消费序列时“观察”序列的方式是否正确。我已经阅读了以下 SO 答案,但我有点惊讶,因为我已经多次阅读“正确”的方法是使用懒惰(因此明确地使您的序列变得懒惰,即使它不是),但那里甚至没有提到“懒惰”这个词:

How to implement the Observer Design Pattern in a pure functional way?

所以基本上我有一个懒惰的序列,我想保持那个懒惰的序列 100% 纯,我不希望观察者将任何东西泄漏到那个懒惰的序列中。在我的例子中,我只是使用 (range 100000)但任何懒惰的序列都可以。

然后我使用了一些可变性(在 Clojure 中使用原子)做这样的事情(代码是可运行的,你可以像在 REPL 中一样复制/粘贴):

(let [a (atom (range 100000))]
(loop [i 0]
(if (= 0 (mod i 10)) (println "i: " i)) ; the observer
(if (= 100 i)
(take 1 @a)
(do (reset! a (rest @a)) (recur (inc i))))))

关键不是我在这里使用的是可变原子,而是惰性序列的实现根本不知道它正在被观察。观察者显然可以更高级:就像实际通知观察者而不是使用副作用来打印 i(再一次:在这里打印 i 只是一个例子)。

这是在消耗惰性序列时进行观察的“正确”方式吗?

如果这不正确,在 Clojure 中使用惰性序列时您将如何观察?

或者,你会如何在 Haskell 中做到这一点?

最佳答案

如果你只是想在消费过程中穿插一个副作用,那么是的,在 Clojure 中做的明智的事情是包装在另一个惰性序列中。

(defn lazy-report
"Wrap s in a lazy sequence that will call f, presumably for side effects,
on every nth element of s during consumption."
[s f n]
(let [g (cons (comp first (juxt identity f)) (repeat (dec n) identity))]
(map #(% %2) (rest (cycle g)) s)))

(println "sum:" (reduce + (lazy-report (range 1 1000) #(println "at:" %) 100)))
;=> at: 100
; at: 200
; ...
; at: 900
; sum: 499500

关于haskell - 如何在使用惰性序列时观察进度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24597228/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com