module JoinList where
import Data.Monoid
-
+import Sized
data JoinList m a = Empty
| Single m a
x +++ Empty = x
alst1 +++ alst2 = Append ((tag alst1) `mappend` (tag alst2)) alst1 alst2
+-- exercise 2
+-- 1. index
+indexJ :: (Sized b, Monoid b) =>
+ Int -> JoinList b a -> Maybe a
+indexJ _ Empty = Nothing
+indexJ n _ | n < 0 = Nothing
+indexJ n (Single _ a) | n == 0 = Just a
+ | otherwise = Nothing
+indexJ n (Append t l r) | n >= getSize (size t) = Nothing
+ | n < 0 = Nothing
+ | n < (getSize (size (tag l))) = indexJ n l
+ | otherwise = indexJ (n - getSize (size (tag l))) r
+
+-- 2. drop
+dropJ :: (Sized b, Monoid b) =>
+ Int -> JoinList b a -> JoinList b a
+dropJ n x | n < 0 = x
+dropJ 0 x = x
+dropJ _ Empty = Empty
+dropJ n v@(Single _ _) | n == 0 = v
+ | otherwise = Empty
+dropJ n (Append t l r) | n > getSize (size t) = Empty
+ | n > leftSize =
+ dropJ (n - leftSize) r
+ | otherwise = let lft = dropJ n l in
+ Append ((tag lft) `mappend` (tag r)) lft r
+ where leftSize = getSize . size . tag $ l
+
+-- 3. take
+takeJ :: (Sized b, Monoid b) =>
+ Int -> JoinList b a -> JoinList b a
+takeJ 0 _ = Empty
+takeJ n _ | n < 0 = Empty
+takeJ _ Empty = Empty
+takeJ n v@(Single _ _) | n == 0 = v
+ | otherwise = Empty
+takeJ n v@(Append t l r) | n > getSize (size t) = v
+ | n < leftSize = takeJ n l
+ | otherwise = let rt = takeJ (n - leftSize) r in
+ Append ((tag l) `mappend` (tag rt)) l rt
+ where leftSize = getSize . size . tag $ l
+