gpt4 book ai didi

sorting - 你能在 Clojure 中将插入排序表述为一个幺半群吗?

转载 作者:行者123 更新时间:2023-12-04 19:06:58 26 4
gpt4 key购买 nike

这是 Clojure 中插入排序的代码:

(defn in-sort! [data]
(letfn [(insert ([raw x](insert [] raw x))
([sorted [y & raw] x]
(if (nil? y) (conj sorted x)
(if (<= x y ) (concat sorted [x,y] raw)
(recur (conj sorted y) raw x )))))]
(reduce insert [] data)))
;Usage:(in-sort! [6,8,5,9,3,2,1,4,7])
;Returns: [1 2 3 4 5 6 7 8 9]

这是 the insertion sort formulated as a monoid在 haskell :

newtype OL x = OL [x]
instance Ord x => Monoid (OL x) where
mempty = OL []
mappend (OL xs) (OL ys) = OL (merge xs ys) where
merge [] ys = ys
merge xs [] = xs
merge xs@(x : xs') ys@(y : ys')
| x <= y = x : merge xs' ys
| otherwise = y : merge xs ys'

isort :: Ord x => [x] -> OL x
isort = foldMap (OL . pure)

This is how在 Clojure 中编写一个幺半群:

(def  mempty (+)) ;; 0
(def mappend +)
(defn mconcat [ms]
(reduce mappend mempty ms))

(mappend 3 4) ;; 7

(mconcat [2 3 4]) ;; 9

我的问题是: 你能在 Clojure 中将插入排序表述为一个幺半群吗?

最佳答案

这是我的尝试,虽然可能不是最好的:)

它是 Haskell 半群的直接翻译。因为我们在 Clojure 中没有自动柯里化(Currying),所以我需要制作一个特殊的 comp-2功能。

(defn comp-2 [f g]
(fn [x y] (f (g x) (g y))))

(defn pure-list [x]
(cond
(sequential? x) (if (empty? x) '() (seq x))
:else (list x)))

(def OL-mempty (list))
(defn OL-mappend [xs ys]
(letfn [(merge [xs ys]
(cond
(empty? xs) ys
(empty? ys) xs
:else (let [[x & xs'] xs
[y & ys'] ys]
(if (<= x y)
(cons x (lazy-seq (merge xs' ys)))
(cons y (lazy-seq (merge xs ys')))))))]
(doall (merge xs ys))))

(defn foldmap [mempty mappend l]
(reduce mappend mempty l))

(def i-sort (partial foldmap OL-mempty (comp-2 OL-mappend pure-list)))
(i-sort (list 5 3 4 1 2 6)) ;; (1 2 3 4 5 6)

这是一篇关于 morphisms in sorts 的非常好的论文的链接。 .

与 reducer 的兼容性

如果我们想使用 Reducers 风格的幺半群,那么我们可以在我们的“ mempty”中嵌入“ mappend”作为零参数分支。一旦我们这样做了,我们就可以让我们的 monoid 立即适合 Reducers 库:

(require '[clojure.core.reducers :as re])

(defn pure-list [x]
(cond
(sequential? x) (if (empty? x) '() (seq x))
:else (list x)))

(defn sort-monoid
([] '()) ;; mempty
([xs ys] ;; mappend
(letfn [(merge [xs ys]
(cond
(empty? xs) ys
(empty? ys) xs
:else (let [[x & xs'] xs
[y & ys'] ys]
(if (<= x y)
(cons x (lazy-seq (merge xs' ys)))
(cons y (lazy-seq (merge xs ys')))))))]
(doall (merge (pure-list xs) (pure-list ys))))))

(re/reduce sort-monoid (list 2 4 1 2 5))

关于sorting - 你能在 Clojure 中将插入排序表述为一个幺半群吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21984769/

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