haskell - index function for balanced binary tree -


i have problem, can't figure out how must decide sub-tree function indexj must choose @ each step walks through balanced binary tree - joinlist.

the idea cache size (number of data elements) of each sub-tree. can used @ each step determine if desired index in left or right branch.

i have code:

data joinlist m = empty                   | single m                   | append m (joinlist m a) (joinlist m a)                   deriving (eq, show)  newtype size = size int   deriving (eq, ord, show, num)  getsize :: size -> int getsize (size i) =  class sized   size :: -> size  instance sized size   size = id  instance monoid size   mempty  = size 0   mappend = (+) 

i write functions:

tag :: monoid m => joinlist m -> m tag empty = mempty tag (single x dt) = x tag (append x l_list r_list) = x  (+++) :: monoid m => joinlist m -> joinlist m -> joinlist m (+++) jl1 jl2 = append (mappend (tag jl1) (tag jl2)) jl1 jl2  indexj :: (sized b, monoid b) => int -> joinlist b -> maybe indexj _ empty = nothing indexj jl | < 0 || (i+1) > (sizejl jl) = nothing     sizejl = getsize . size . tag  indexj 0 (single m d) = d indexj 0 (append m (single sz1 dt1) jl2) = dt1 indexj (append m jl1 jl2) = if (sizejl jl1) >= (sizejl jl2)                                indexj (i-1) jl1                                 else indexj (i-1) jl2     sizejl = getsize . size . tag 

functions tag , (+++) working well, need finish indexj function, must return i-th element joinlist tree, = [0..n]

my function indexj working wrong =) if have empty tree - it's (size 0) if have single (size 1) "data" - it's (size 1) if have append (size 2) (single (size 1) 'k') (single (size 1) 'l') branch must choose? i-1 = 1 , have 2 branches 1 data element in each.

update: if needs take , drop functions joinlist's trees make it:

dropj :: (sized b, monoid b) => int -> joinlist b -> joinlist b dropj _ empty = empty  dropj n jl | n <= 0 = jl dropj n jl | n >= (getsize . size $ tag jl) = empty dropj n (append m jl1 jl2)   | n == s1 = jl2   | n < s1 = (dropj n jl1) +++ jl2   | otherwise = dropj (n - s1) jl2                 s1 = getsize . size $ tag jl1  takej :: (sized b, monoid b) => int -> joinlist b -> joinlist b takej _ empty = empty  takej n jl | n <= 0 = empty takej n jl | n >= (getsize . size $ tag jl) = jl takej n (append m jl1 jl2)   | n == s1 = jl1   | n < s1 = (takej n jl1)   | otherwise = jl1 +++ takej (n - s1) jl2                 s1 = getsize . size $ tag jl1 

i suppose in

append m joinlist1 joinlist2 

the elements of joinlist1 meant take first indices, followed elements of joinlist2.

then, when indexing

indexj (append m jl1 jl2) 

you have compare i size of jl1 - let call s1. elements of jl1 occupy indices 0 s1 - 1, , elements of jl2 occupy indices s1 s1 + s2 - 1, hence

indexj :: (sized b, monoid b) => int -> joinlist b -> maybe indexj _ empty  = nothing indexj (single m d)     | == 0    = d     | otherwise = nothing indexj (append m jl1 jl2)     | < 0     = nothing     | >= getsize (size m) = nothing     -- optional, more efficient have     | < s1    = indexj jl1     | otherwise = indexj (i - s1) jl2               s1 = getsize . size $ tag jl1 

if index smaller s1, in first sublist, otherwise in second.


Comments

Popular posts from this blog

c# - Operator '==' incompatible with operand types 'Guid' and 'Guid' using DynamicExpression.ParseLambda<T, bool> -