这是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]

这是Haskell中的the insertion sort formulated as a monoid:

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中编写一个monoid:

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

(mappend 3 4) ;; 7

(mconcat [2 3 4]) ;; 9

我的问题是:您能在Clojure中将插入排序表述为类吗?

最佳答案

作为引用,这里是另一个版本,该版本使用累加器将tail recursion modulo cons转换为尾递归。出于多样性的考虑,这也是部分模拟不存在的类型类的一种方法。

(defprotocol Monoid
  (mempty [_] )
  (mappend [_ xs ys]))

(defn fold-map
  [monoid f xs]
  (reduce (partial mappend monoid) (mempty monoid) (map f xs)))

(defn- ord-mappend*
  [[x & rx :as xs] [y & ry :as ys] a]
  (cond
    (empty? xs) (concat a ys)
    (empty? ys) (concat a xs)
    :else (if (< x y)
             (recur rx ys (conj a x))
             (recur xs ry (conj a y)))))

(def Ord
  (reify Monoid
    (mempty [_] (list))
    (mappend [_ xs ys] (ord-mappend* xs ys []))))

(defn isort [xs] (fold-map Ord list xs))

(defn is-sorted? [xs] (apply < xs))

(is-sorted? (isort (shuffle (range 10000))))
;=> true (sometime later)

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

10-10 02:39