Binomial.hs (2810B)
1 {-# OPTIONS_GHC -Wall -fno-warn-unused-top-binds #-} 2 {-# LANGUAGE TemplateHaskell #-} 3 4 module Okasaki.Heap.Binomial where 5 6 import Data.Eq.Deriving (deriveEq1) 7 import Data.Fix hiding (cata, ana, hylo) 8 import Data.Foldable (toList) 9 import Data.Functor.Foldable 10 import Data.List (sortOn) 11 import Data.List.NonEmpty (NonEmpty(..)) 12 import Data.Maybe (fromMaybe) 13 import Text.Show.Deriving 14 15 data TreeF a r = NodeF a [r] 16 deriving (Eq, Show, Functor, Foldable, Traversable) 17 18 type Tree a = Fix (TreeF a) 19 20 $(deriveShow1 ''TreeF) 21 $(deriveEq1 ''TreeF) 22 23 -- exercise 3.6: remove redundant rank info 24 data Bush a = Bush {-# UNPACK #-} !Int !(Tree a) 25 deriving Show 26 27 newtype Heap a = Heap [Bush a] 28 deriving Show 29 30 lef :: Heap a 31 lef = Heap [] 32 33 nod :: a -> [Tree a] -> Tree a 34 nod a t = Fix (NodeF a t) 35 36 lin :: Ord a => Bush a -> Bush a -> Bush a 37 lin (Bush i s@(project -> NodeF a c)) (Bush j t@(project -> NodeF b d)) 38 | i /= j = error "(okasaki, binomial): internal error" 39 | a <= b = Bush (succ i) (nod a (t : c)) 40 | otherwise = Bush (succ i) (nod b (s : d)) 41 42 ran :: Bush a -> Int 43 ran (Bush i _) = i 44 45 roo :: Bush a -> a 46 roo (Bush _ (project -> NodeF a _)) = a 47 48 pet :: Ord a => Bush a -> [Bush a] -> [Bush a] 49 pet a as = toList $ cata alg as (a :| as) 50 where 51 alg l n@(t :| ts) = case l of 52 Nil -> n 53 Cons h f 54 | ran t < ran h -> n 55 | otherwise -> f $! lin t h :| drop 1 ts 56 57 put :: Ord a => a -> Heap a -> Heap a 58 put a (Heap as) = Heap $ 59 pet (Bush 0 (nod a [])) as 60 61 mer :: Ord a => Heap a -> Heap a -> Heap a 62 mer (Heap a) (Heap b) = Heap $ mor a b where 63 mor l r = case (l, r) of 64 (p, []) -> p 65 ([], q) -> q 66 (h : t, i : s) 67 | ran h < ran i -> h : mor t r 68 | ran i < ran h -> i : mor l s 69 | otherwise -> pet (lin h i) (mor t s) 70 71 out :: Ord a => Heap a -> Maybe (Bush a, Heap a) 72 out (Heap as) = case as of 73 [] -> Nothing 74 (h : []) -> Just (h, lef) 75 (h : t) -> do 76 (i, Heap s) <- out (Heap t) 77 pure $ if roo h <= roo i 78 then (h, Heap t) 79 else (i, Heap (h:s)) 80 81 bot :: Ord a => Heap a -> Maybe a 82 bot h = do 83 (a, _) <- out h 84 pure $ roo a 85 86 -- exercise 3.5: direct bot 87 bed :: Ord a => Heap a -> Maybe a 88 bed (Heap a) = case sortOn roo a of 89 [] -> Nothing 90 (h : _) -> Just (roo h) 91 92 cut :: Ord a => Heap a -> Heap a 93 cut h = fromMaybe lef $ do 94 (Bush i (project -> NodeF _ s), t) <- out h 95 let p = fmap (Bush (pred i)) s 96 pure $ mer (Heap (reverse p)) t 97 98 -- reference 99 100 -- arbitrary recursion 101 pyt :: Ord a => Bush a -> Heap a -> Heap a 102 pyt a (Heap as) = Heap (loop a as) where 103 loop s ts = case ts of 104 [] -> pure s 105 (h : t) 106 | ran s < ran h -> s : ts 107 | otherwise -> loop (lin s h) t 108 109 -- test 110 111 test0 :: Heap Int 112 test0 = put 3 . put 2 . put 1 . put 0 $ lef 113 114 test1 :: Heap Int 115 test1 = put 4 test0