okasaki

Okasaki's Purely Functional Data Structures
Log | Files | Refs | LICENSE

commit e95b660dcc16ee7033490c0b2cb714308fa87a5d
parent f857cb080adef27071a1817b6e49a8249d41a531
Author: Jared Tobin <jared@jtobin.io>
Date:   Wed,  5 Apr 2023 21:28:22 +0400

Remove redundant binomial heap rank info.

Diffstat:
Mlib/Okasaki/Heap/Binomial.hs | 49++++++++++++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/lib/Okasaki/Heap/Binomial.hs b/lib/Okasaki/Heap/Binomial.hs @@ -1,4 +1,5 @@ {-# OPTIONS_GHC -Wall -fno-warn-unused-top-binds #-} +{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE TemplateHaskell #-} module Okasaki.Heap.Binomial where @@ -7,11 +8,12 @@ import Data.Eq.Deriving (deriveEq1) import Data.Fix hiding (cata, ana, hylo) import Data.Foldable (toList) import Data.Functor.Foldable +import Data.List (sortOn) import Data.List.NonEmpty (NonEmpty(..)) import Data.Maybe (fromMaybe) import Text.Show.Deriving -data TreeF a r = NodeF !Int a [r] +data TreeF a r = NodeF a [r] deriving (Eq, Show, Functor, Foldable, Traversable) type Tree a = Fix (TreeF a) @@ -19,28 +21,32 @@ type Tree a = Fix (TreeF a) $(deriveShow1 ''TreeF) $(deriveEq1 ''TreeF) -newtype Heap a = Heap [Tree a] +-- exercise 3.6: remove redundant rank info +data Bush a = Bush {-# UNPACK #-} !Int !(Tree a) + deriving Show + +newtype Heap a = Heap [Bush a] deriving Show lef :: Heap a lef = Heap [] -nod :: Int -> a -> [Tree a] -> Tree a -nod r a t = Fix (NodeF r a t) +nod :: a -> [Tree a] -> Tree a +nod a t = Fix (NodeF a t) -lin :: Ord a => Tree a -> Tree a -> Tree a -lin s@(project -> NodeF r a c) t@(project -> NodeF q b d) - | r /= q = error "(okasaki, binomial): internal error" - | a <= b = nod (succ r) a (t : c) - | otherwise = nod (succ r) b (s : d) +lin :: Ord a => Bush a -> Bush a -> Bush a +lin (Bush i s@(project -> NodeF a c)) (Bush j t@(project -> NodeF b d)) + | i /= j = error "(okasaki, binomial): internal error" + | a <= b = Bush (succ i) (nod a (t : c)) + | otherwise = Bush (succ i) (nod b (s : d)) -ran :: Tree a -> Int -ran (project -> NodeF r _ _) = r +ran :: Bush a -> Int +ran (Bush i _) = i -roo :: Tree a -> a -roo (project -> NodeF _ a _) = a +roo :: Bush a -> a +roo (Bush _ (project -> NodeF a _)) = a -pet :: Ord a => Tree a -> [Tree a] -> [Tree a] +pet :: Ord a => Bush a -> [Bush a] -> [Bush a] pet a as = toList $ cata alg as (a :| as) where alg l n@(t :| ts) = case l of @@ -51,7 +57,7 @@ pet a as = toList $ cata alg as (a :| as) put :: Ord a => a -> Heap a -> Heap a put a (Heap as) = Heap $ - pet (nod 0 a []) as + pet (Bush 0 (nod a [])) as mer :: Ord a => Heap a -> Heap a -> Heap a mer (Heap a) (Heap b) = Heap $ mor a b where @@ -63,7 +69,7 @@ mer (Heap a) (Heap b) = Heap $ mor a b where | ran i < ran h -> i : mor l s | otherwise -> pet (lin h i) (mor t s) -out :: Ord a => Heap a -> Maybe (Tree a, Heap a) +out :: Ord a => Heap a -> Maybe (Bush a, Heap a) out (Heap as) = case as of [] -> Nothing (h : []) -> Just (h, lef) @@ -79,20 +85,21 @@ bot h = do pure $ roo a -- exercise 3.5: direct bot -bed :: Heap a -> Maybe a -bed (Heap a) = case a of +bed :: Ord a => Heap a -> Maybe a +bed (Heap a) = case sortOn roo a of [] -> Nothing (h : _) -> Just (roo h) cut :: Ord a => Heap a -> Heap a cut h = fromMaybe lef $ do - (project -> NodeF _ _ s, t) <- out h - pure $ mer (Heap (reverse s)) t + (Bush i (project -> NodeF _ s), t) <- out h + let p = fmap (Bush (pred i)) s + pure $ mer (Heap (reverse p)) t -- reference -- arbitrary recursion -pyt :: Ord a => Tree a -> Heap a -> Heap a +pyt :: Ord a => Bush a -> Heap a -> Heap a pyt a (Heap as) = Heap (loop a as) where loop s ts = case ts of [] -> pure s