Originally I posted this incorrect attempt - Searching a Join List for an index.
Given a JoinList
:
data JoinList m a = Empty
| Single m a
| Append m (JoinList m a) (JoinList m a)
deriving (Eq, Show)
where m
represents the size of the JoinList
, find the element (Maybe a)
at the given index in the JoinList
structure.
indexJ :: (Sized b, Monoid b) => Int -> JoinList b a -> Maybe a
indexJ _ Empty = Nothing
indexJ i (Single _ x)
| i == 0 = Just x
| otherwise = Nothing
indexJ i (Append _ left right)
| leftHt > i = indexJ i left
| (rightHt + leftHt) > i = indexJ (i-leftHt) right
| otherwise = Nothing
where leftHt = (getSize. size . tag) left
rightHt = (getSize. size . tag) right
where tag
=
tag :: Monoid m => JoinList m a -> m
tag Empty = mempty
tag (Single x _) = x
tag (Append x _ _) = x
Testing
Data
jlIndex2 :: JoinList Size String
jlIndex2 = Append (Size 3)
(Single (Size 1) "foo")
(Append (Size 2)
(Single (Size 1) "bar")
(Single (Size 1) "baz"))
jlIndex3 :: JoinList Size String
jlIndex3 = Append (Size 4) (Single 1 "biz") jlIndex2
Tests
*JoinList> indexJ 3 jlIndex3
Just "baz"
*JoinList> indexJ 0 jlIndex3
Just "biz"
*JoinList> indexJ 100 jlIndex3
Nothing
Note - I would've used QuickCheck, but I'm not sure how to use it with algebraic data types.