from __future__ import annotations
from typing import (TypeVar, Generic, Optional, Any, Tuple, Callable, List)
from .array import (fill, map as map_2)
from .list import (FSharpList, cons, empty as empty_1, fold as fold_1, is_empty as is_empty_1, tail, head, of_array_with_tail, singleton)
from .option import (value as value_1, some)
from .reflection import (TypeInfo, class_type, option_type, list_type, bool_type, record_type)
from .seq import (unfold, map as map_1, compare_with, iterate as iterate_1, pick as pick_1, try_pick as try_pick_1)
from .string import (join, format)
from .types import (Record, FSharpRef)
from .util import (IComparer, IEnumerator, IEnumerable, is_array_like, get_enumerator, equals, to_iterator, compare, ignore, ICollection, structural_hash)

_KEY = TypeVar("_KEY")

_VALUE = TypeVar("_VALUE")

_A_ = TypeVar("_A_")

_B_ = TypeVar("_B_")

_C_ = TypeVar("_C_")

_RESULT = TypeVar("_RESULT")

_Z = TypeVar("_Z")

_B = TypeVar("_B")

_STATE = TypeVar("_STATE")

_T = TypeVar("_T")

_K = TypeVar("_K")

_V = TypeVar("_V")

def expr_266(gen0: TypeInfo, gen1: TypeInfo) -> TypeInfo:
    return class_type("Map.MapTreeLeaf`2", [gen0, gen1], MapTreeLeaf_2)


class MapTreeLeaf_2(Generic[_KEY, _VALUE]):
    def __init__(self, k: _KEY, v: _VALUE) -> None:
        self.k = k
        self.v = v
    

MapTreeLeaf_2_reflection = expr_266

def MapTreeLeaf_2__ctor_5BDDA1(k: _KEY, v: _VALUE) -> MapTreeLeaf_2[_KEY, _VALUE]:
    return MapTreeLeaf_2(k, v)


def MapTreeLeaf_2__get_Key(_: MapTreeLeaf_2[_KEY, _VALUE]) -> _KEY:
    return _.k


def MapTreeLeaf_2__get_Value(_: MapTreeLeaf_2[_KEY, _VALUE]) -> _VALUE:
    return _.v


def expr_267(gen0: TypeInfo, gen1: TypeInfo) -> TypeInfo:
    return class_type("Map.MapTreeNode`2", [gen0, gen1], MapTreeNode_2, MapTreeLeaf_2_reflection(gen0, gen1))


class MapTreeNode_2(MapTreeLeaf_2, Generic[_KEY, _VALUE]):
    def __init__(self, k: _KEY, v: _VALUE, left: Optional[MapTreeLeaf_2[_KEY, _VALUE]], right: Optional[MapTreeLeaf_2[_KEY, _VALUE]], h: int) -> None:
        super().__init__(k, v)
        self.left = left
        self.right = right
        self.h = h or 0
    

MapTreeNode_2_reflection = expr_267

def MapTreeNode_2__ctor_Z39DE9543(k: _KEY, v: _VALUE, left: Optional[MapTreeLeaf_2[_KEY, _VALUE]], right: Optional[MapTreeLeaf_2[_KEY, _VALUE]], h: int) -> MapTreeNode_2[_KEY, _VALUE]:
    return MapTreeNode_2(k, v, left, right, h)


def MapTreeNode_2__get_Left(_: MapTreeNode_2[_KEY, _VALUE]) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    return _.left


def MapTreeNode_2__get_Right(_: MapTreeNode_2[_KEY, _VALUE]) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    return _.right


def MapTreeNode_2__get_Height(_: MapTreeNode_2[_KEY, _VALUE]) -> int:
    return _.h


def MapTreeModule_empty() -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    return None


def MapTreeModule_sizeAux(acc_mut: int, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> int:
    while True:
        (acc, m) = (acc_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                acc_mut = MapTreeModule_sizeAux(acc + 1, MapTreeNode_2__get_Left(m2))
                m_mut = MapTreeNode_2__get_Right(m2)
                continue
            
            else: 
                return acc + 1
            
        
        else: 
            return acc
        
        break


def MapTreeModule_size(x: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> int:
    return MapTreeModule_sizeAux(0, x)


def MapTreeModule_mk(l: Optional[MapTreeLeaf_2[_KEY, _VALUE]], k: _KEY, v: _VALUE, r: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    hl : int
    m : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = l
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        hl = MapTreeNode_2__get_Height(m2) if isinstance(m2, MapTreeNode_2) else 1
    
    else: 
        hl = 0
    
    hr : int
    m_1 : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = r
    if m_1 is not None:
        m2_1 : MapTreeLeaf_2[_KEY, _VALUE] = m_1
        hr = MapTreeNode_2__get_Height(m2_1) if isinstance(m2_1, MapTreeNode_2) else 1
    
    else: 
        hr = 0
    
    m_2 : int = (hr if (hl < hr) else hl) or 0
    if m_2 == 0:
        return MapTreeLeaf_2__ctor_5BDDA1(k, v)
    
    else: 
        return MapTreeNode_2__ctor_Z39DE9543(k, v, l, r, m_2 + 1)
    


def MapTreeModule_rebalance(t1: Optional[MapTreeLeaf_2[_KEY, _VALUE]], k: _KEY, v: _VALUE, t2: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    t1h : int
    m : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = t1
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        t1h = MapTreeNode_2__get_Height(m2) if isinstance(m2, MapTreeNode_2) else 1
    
    else: 
        t1h = 0
    
    t2h : int
    m_1 : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = t2
    if m_1 is not None:
        m2_1 : MapTreeLeaf_2[_KEY, _VALUE] = m_1
        t2h = MapTreeNode_2__get_Height(m2_1) if isinstance(m2_1, MapTreeNode_2) else 1
    
    else: 
        t2h = 0
    
    if t2h > (t1h + 2):
        match_value : MapTreeLeaf_2[_KEY, _VALUE] = value_1(t2)
        if isinstance(match_value, MapTreeNode_2):
            def arrow_268(t1: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=t1, k: _KEY=k, v: _VALUE=v, t2: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=t2) -> int:
                m_2 : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = MapTreeNode_2__get_Left(match_value)
                if m_2 is not None:
                    m2_2 : MapTreeLeaf_2[_KEY, _VALUE] = m_2
                    return MapTreeNode_2__get_Height(m2_2) if isinstance(m2_2, MapTreeNode_2) else 1
                
                else: 
                    return 0
                
            
            if arrow_268() > (t1h + 1):
                match_value_1 : MapTreeLeaf_2[_KEY, _VALUE] = value_1(MapTreeNode_2__get_Left(match_value))
                if isinstance(match_value_1, MapTreeNode_2):
                    return MapTreeModule_mk(MapTreeModule_mk(t1, k, v, MapTreeNode_2__get_Left(match_value_1)), MapTreeLeaf_2__get_Key(match_value_1), MapTreeLeaf_2__get_Value(match_value_1), MapTreeModule_mk(MapTreeNode_2__get_Right(match_value_1), MapTreeLeaf_2__get_Key(match_value), MapTreeLeaf_2__get_Value(match_value), MapTreeNode_2__get_Right(match_value)))
                
                else: 
                    raise Exception("internal error: Map.rebalance")
                
            
            else: 
                return MapTreeModule_mk(MapTreeModule_mk(t1, k, v, MapTreeNode_2__get_Left(match_value)), MapTreeLeaf_2__get_Key(match_value), MapTreeLeaf_2__get_Value(match_value), MapTreeNode_2__get_Right(match_value))
            
        
        else: 
            raise Exception("internal error: Map.rebalance")
        
    
    elif t1h > (t2h + 2):
        match_value_2 : MapTreeLeaf_2[_KEY, _VALUE] = value_1(t1)
        if isinstance(match_value_2, MapTreeNode_2):
            def arrow_269(t1: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=t1, k: _KEY=k, v: _VALUE=v, t2: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=t2) -> int:
                m_3 : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = MapTreeNode_2__get_Right(match_value_2)
                if m_3 is not None:
                    m2_3 : MapTreeLeaf_2[_KEY, _VALUE] = m_3
                    return MapTreeNode_2__get_Height(m2_3) if isinstance(m2_3, MapTreeNode_2) else 1
                
                else: 
                    return 0
                
            
            if arrow_269() > (t2h + 1):
                match_value_3 : MapTreeLeaf_2[_KEY, _VALUE] = value_1(MapTreeNode_2__get_Right(match_value_2))
                if isinstance(match_value_3, MapTreeNode_2):
                    return MapTreeModule_mk(MapTreeModule_mk(MapTreeNode_2__get_Left(match_value_2), MapTreeLeaf_2__get_Key(match_value_2), MapTreeLeaf_2__get_Value(match_value_2), MapTreeNode_2__get_Left(match_value_3)), MapTreeLeaf_2__get_Key(match_value_3), MapTreeLeaf_2__get_Value(match_value_3), MapTreeModule_mk(MapTreeNode_2__get_Right(match_value_3), k, v, t2))
                
                else: 
                    raise Exception("internal error: Map.rebalance")
                
            
            else: 
                return MapTreeModule_mk(MapTreeNode_2__get_Left(match_value_2), MapTreeLeaf_2__get_Key(match_value_2), MapTreeLeaf_2__get_Value(match_value_2), MapTreeModule_mk(MapTreeNode_2__get_Right(match_value_2), k, v, t2))
            
        
        else: 
            raise Exception("internal error: Map.rebalance")
        
    
    else: 
        return MapTreeModule_mk(t1, k, v, t2)
    


def MapTreeModule_add(comparer: IComparer[_KEY], k: _KEY, v: _VALUE, m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        c : int = comparer.Compare(k, MapTreeLeaf_2__get_Key(m2)) or 0
        if isinstance(m2, MapTreeNode_2):
            if c < 0:
                return MapTreeModule_rebalance(MapTreeModule_add(comparer, k, v, MapTreeNode_2__get_Left(m2)), MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeNode_2__get_Right(m2))
            
            elif c == 0:
                return MapTreeNode_2__ctor_Z39DE9543(k, v, MapTreeNode_2__get_Left(m2), MapTreeNode_2__get_Right(m2), MapTreeNode_2__get_Height(m2))
            
            else: 
                return MapTreeModule_rebalance(MapTreeNode_2__get_Left(m2), MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeModule_add(comparer, k, v, MapTreeNode_2__get_Right(m2)))
            
        
        elif c < 0:
            return MapTreeNode_2__ctor_Z39DE9543(k, v, MapTreeModule_empty(), m, 2)
        
        elif c == 0:
            return MapTreeLeaf_2__ctor_5BDDA1(k, v)
        
        else: 
            return MapTreeNode_2__ctor_Z39DE9543(k, v, m, MapTreeModule_empty(), 2)
        
    
    else: 
        return MapTreeLeaf_2__ctor_5BDDA1(k, v)
    


def MapTreeModule_tryFind(comparer_mut: IComparer[_KEY], k_mut: _KEY, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> Optional[_VALUE]:
    while True:
        (comparer, k, m) = (comparer_mut, k_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            c : int = comparer.Compare(k, MapTreeLeaf_2__get_Key(m2)) or 0
            if c == 0:
                return some(MapTreeLeaf_2__get_Value(m2))
            
            elif isinstance(m2, MapTreeNode_2):
                comparer_mut = comparer
                k_mut = k
                m_mut = MapTreeNode_2__get_Left(m2) if (c < 0) else MapTreeNode_2__get_Right(m2)
                continue
            
            else: 
                return None
            
        
        else: 
            return None
        
        break


def MapTreeModule_find(comparer: IComparer[_KEY], k: _KEY, m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> _VALUE:
    match_value : Optional[_VALUE] = MapTreeModule_tryFind(comparer, k, m)
    if match_value is None:
        raise Exception()
    
    else: 
        return value_1(match_value)
    


def MapTreeModule_partition1(comparer: IComparer[_KEY], f: Any, k: _KEY, v: _A_, acc1: Optional[MapTreeLeaf_2[_KEY, _A_]]=None, acc2: Optional[MapTreeLeaf_2[_KEY, _A_]]=None) -> Tuple[Optional[MapTreeLeaf_2[_KEY, _A_]], Optional[MapTreeLeaf_2[_KEY, _A_]]]:
    if f(k, v):
        return (MapTreeModule_add(comparer, k, v, acc1), acc2)
    
    else: 
        return (acc1, MapTreeModule_add(comparer, k, v, acc2))
    


def MapTreeModule_partitionAux(comparer_mut: IComparer[_KEY], f_mut: Any, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]], acc_0_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]], acc_1_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> Tuple[Optional[MapTreeLeaf_2[_KEY, _VALUE]], Optional[MapTreeLeaf_2[_KEY, _VALUE]]]:
    while True:
        (comparer, f, m, acc_0, acc_1) = (comparer_mut, f_mut, m_mut, acc_0_mut, acc_1_mut)
        acc : Tuple[Optional[MapTreeLeaf_2[_KEY, _VALUE]], Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = (acc_0, acc_1)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                acc_2 : Tuple[Optional[MapTreeLeaf_2[_KEY, _VALUE]], Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = MapTreeModule_partitionAux(comparer, f, MapTreeNode_2__get_Right(m2), acc[0], acc[1])
                acc_3 : Tuple[Optional[MapTreeLeaf_2[_KEY, _VALUE]], Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = MapTreeModule_partition1(comparer, f, MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), acc_2[0], acc_2[1])
                comparer_mut = comparer
                f_mut = f
                m_mut = MapTreeNode_2__get_Left(m2)
                acc_0_mut = acc_3[0]
                acc_1_mut = acc_3[1]
                continue
            
            else: 
                return MapTreeModule_partition1(comparer, f, MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), acc[0], acc[1])
            
        
        else: 
            return acc
        
        break


def MapTreeModule_partition(comparer: IComparer[_KEY], f: Callable[[_KEY, _A_], bool], m: Optional[MapTreeLeaf_2[_KEY, _A_]]=None) -> Tuple[Optional[MapTreeLeaf_2[_KEY, _A_]], Optional[MapTreeLeaf_2[_KEY, _A_]]]:
    return MapTreeModule_partitionAux(comparer, f, m, MapTreeModule_empty(), MapTreeModule_empty())


def MapTreeModule_filter1(comparer: IComparer[_KEY], f: Any, k: _KEY, v: _A_, acc: Optional[MapTreeLeaf_2[_KEY, _A_]]=None) -> Optional[MapTreeLeaf_2[_KEY, _A_]]:
    if f(k, v):
        return MapTreeModule_add(comparer, k, v, acc)
    
    else: 
        return acc
    


def MapTreeModule_filterAux(comparer_mut: IComparer[_KEY], f_mut: Any, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]], acc_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    while True:
        (comparer, f, m, acc) = (comparer_mut, f_mut, m_mut, acc_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                acc_1 : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = MapTreeModule_filterAux(comparer, f, MapTreeNode_2__get_Left(m2), acc)
                acc_2 : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = MapTreeModule_filter1(comparer, f, MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), acc_1)
                comparer_mut = comparer
                f_mut = f
                m_mut = MapTreeNode_2__get_Right(m2)
                acc_mut = acc_2
                continue
            
            else: 
                return MapTreeModule_filter1(comparer, f, MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), acc)
            
        
        else: 
            return acc
        
        break


def MapTreeModule_filter(comparer: IComparer[_KEY], f: Callable[[_KEY, _A_], bool], m: Optional[MapTreeLeaf_2[_KEY, _A_]]=None) -> Optional[MapTreeLeaf_2[_KEY, _A_]]:
    return MapTreeModule_filterAux(comparer, f, m, MapTreeModule_empty())


def MapTreeModule_spliceOutSuccessor(m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Tuple[_KEY, _VALUE, Optional[MapTreeLeaf_2[_KEY, _VALUE]]]:
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        if isinstance(m2, MapTreeNode_2):
            if MapTreeNode_2__get_Left(m2) is None:
                return (MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeNode_2__get_Right(m2))
            
            else: 
                pattern_input : Tuple[_KEY, _VALUE, Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = MapTreeModule_spliceOutSuccessor(MapTreeNode_2__get_Left(m2))
                return (pattern_input[0], pattern_input[1], MapTreeModule_mk(pattern_input[2], MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeNode_2__get_Right(m2)))
            
        
        else: 
            return (MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeModule_empty())
        
    
    else: 
        raise Exception("internal error: Map.spliceOutSuccessor")
    


def MapTreeModule_remove(comparer: IComparer[_KEY], k: _KEY, m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        c : int = comparer.Compare(k, MapTreeLeaf_2__get_Key(m2)) or 0
        if isinstance(m2, MapTreeNode_2):
            if c < 0:
                return MapTreeModule_rebalance(MapTreeModule_remove(comparer, k, MapTreeNode_2__get_Left(m2)), MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeNode_2__get_Right(m2))
            
            elif c == 0:
                if MapTreeNode_2__get_Left(m2) is None:
                    return MapTreeNode_2__get_Right(m2)
                
                elif MapTreeNode_2__get_Right(m2) is None:
                    return MapTreeNode_2__get_Left(m2)
                
                else: 
                    pattern_input : Tuple[_KEY, _VALUE, Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = MapTreeModule_spliceOutSuccessor(MapTreeNode_2__get_Right(m2))
                    return MapTreeModule_mk(MapTreeNode_2__get_Left(m2), pattern_input[0], pattern_input[1], pattern_input[2])
                
            
            else: 
                return MapTreeModule_rebalance(MapTreeNode_2__get_Left(m2), MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeModule_remove(comparer, k, MapTreeNode_2__get_Right(m2)))
            
        
        elif c == 0:
            return MapTreeModule_empty()
        
        else: 
            return m
        
    
    else: 
        return MapTreeModule_empty()
    


def MapTreeModule_change(comparer: IComparer[_KEY], k: _KEY, u: Callable[[Optional[_VALUE]], Optional[_VALUE]], m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        if isinstance(m2, MapTreeNode_2):
            c : int = comparer.Compare(k, MapTreeLeaf_2__get_Key(m2)) or 0
            if c < 0:
                return MapTreeModule_rebalance(MapTreeModule_change(comparer, k, u, MapTreeNode_2__get_Left(m2)), MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeNode_2__get_Right(m2))
            
            elif c == 0:
                match_value_1 : Optional[_VALUE] = u(some(MapTreeLeaf_2__get_Value(m2)))
                if match_value_1 is not None:
                    return MapTreeNode_2__ctor_Z39DE9543(k, value_1(match_value_1), MapTreeNode_2__get_Left(m2), MapTreeNode_2__get_Right(m2), MapTreeNode_2__get_Height(m2))
                
                elif MapTreeNode_2__get_Left(m2) is None:
                    return MapTreeNode_2__get_Right(m2)
                
                elif MapTreeNode_2__get_Right(m2) is None:
                    return MapTreeNode_2__get_Left(m2)
                
                else: 
                    pattern_input : Tuple[_KEY, _VALUE, Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = MapTreeModule_spliceOutSuccessor(MapTreeNode_2__get_Right(m2))
                    return MapTreeModule_mk(MapTreeNode_2__get_Left(m2), pattern_input[0], pattern_input[1], pattern_input[2])
                
            
            else: 
                return MapTreeModule_rebalance(MapTreeNode_2__get_Left(m2), MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), MapTreeModule_change(comparer, k, u, MapTreeNode_2__get_Right(m2)))
            
        
        else: 
            c_1 : int = comparer.Compare(k, MapTreeLeaf_2__get_Key(m2)) or 0
            if c_1 < 0:
                match_value_2 : Optional[_VALUE] = u(None)
                if match_value_2 is not None:
                    return MapTreeNode_2__ctor_Z39DE9543(k, value_1(match_value_2), MapTreeModule_empty(), m, 2)
                
                else: 
                    return m
                
            
            elif c_1 == 0:
                match_value_3 : Optional[_VALUE] = u(some(MapTreeLeaf_2__get_Value(m2)))
                if match_value_3 is not None:
                    return MapTreeLeaf_2__ctor_5BDDA1(k, value_1(match_value_3))
                
                else: 
                    return MapTreeModule_empty()
                
            
            else: 
                match_value_4 : Optional[_VALUE] = u(None)
                if match_value_4 is not None:
                    return MapTreeNode_2__ctor_Z39DE9543(k, value_1(match_value_4), m, MapTreeModule_empty(), 2)
                
                else: 
                    return m
                
            
        
    
    else: 
        match_value : Optional[_VALUE] = u(None)
        if match_value is not None:
            return MapTreeLeaf_2__ctor_5BDDA1(k, value_1(match_value))
        
        else: 
            return m
        
    


def MapTreeModule_mem(comparer_mut: IComparer[_KEY], k_mut: _KEY, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> bool:
    while True:
        (comparer, k, m) = (comparer_mut, k_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            c : int = comparer.Compare(k, MapTreeLeaf_2__get_Key(m2)) or 0
            if isinstance(m2, MapTreeNode_2):
                if c < 0:
                    comparer_mut = comparer
                    k_mut = k
                    m_mut = MapTreeNode_2__get_Left(m2)
                    continue
                
                elif c == 0:
                    return True
                
                else: 
                    comparer_mut = comparer
                    k_mut = k
                    m_mut = MapTreeNode_2__get_Right(m2)
                    continue
                
            
            else: 
                return c == 0
            
        
        else: 
            return False
        
        break


def MapTreeModule_iterOpt(f_mut: Any, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> None:
    while True:
        (f, m) = (f_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                MapTreeModule_iterOpt(f, MapTreeNode_2__get_Left(m2))
                f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
                f_mut = f
                m_mut = MapTreeNode_2__get_Right(m2)
                continue
            
            else: 
                f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
            
        
        break


def MapTreeModule_iter(f: Callable[[_A_, _B_], None], m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> None:
    MapTreeModule_iterOpt(f, m)


def MapTreeModule_tryPickOpt(f_mut: Any, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> Optional[_A_]:
    while True:
        (f, m) = (f_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                match_value : Optional[_A_] = MapTreeModule_tryPickOpt(f, MapTreeNode_2__get_Left(m2))
                if match_value is None:
                    match_value_1 : Optional[_A_] = f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
                    if match_value_1 is None:
                        f_mut = f
                        m_mut = MapTreeNode_2__get_Right(m2)
                        continue
                    
                    else: 
                        return match_value_1
                    
                
                else: 
                    return match_value
                
            
            else: 
                return f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
            
        
        else: 
            return None
        
        break


def MapTreeModule_tryPick(f: Callable[[_A_, _B_], Optional[_C_]], m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> Optional[_C_]:
    return MapTreeModule_tryPickOpt(f, m)


def MapTreeModule_existsOpt(f_mut: Any, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> bool:
    while True:
        (f, m) = (f_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                if True if MapTreeModule_existsOpt(f, MapTreeNode_2__get_Left(m2)) else f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2)):
                    return True
                
                else: 
                    f_mut = f
                    m_mut = MapTreeNode_2__get_Right(m2)
                    continue
                
            
            else: 
                return f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
            
        
        else: 
            return False
        
        break


def MapTreeModule_exists(f: Callable[[_A_, _B_], bool], m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> bool:
    return MapTreeModule_existsOpt(f, m)


def MapTreeModule_forallOpt(f_mut: Any, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> bool:
    while True:
        (f, m) = (f_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                if f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2)) if MapTreeModule_forallOpt(f, MapTreeNode_2__get_Left(m2)) else False:
                    f_mut = f
                    m_mut = MapTreeNode_2__get_Right(m2)
                    continue
                
                else: 
                    return False
                
            
            else: 
                return f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
            
        
        else: 
            return True
        
        break


def MapTreeModule_forall(f: Callable[[_A_, _B_], bool], m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> bool:
    return MapTreeModule_forallOpt(f, m)


def MapTreeModule_map(f: Callable[[_VALUE], _RESULT], m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Optional[MapTreeLeaf_2[_KEY, _RESULT]]:
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        if isinstance(m2, MapTreeNode_2):
            l2 : Optional[MapTreeLeaf_2[_KEY, _RESULT]] = MapTreeModule_map(f, MapTreeNode_2__get_Left(m2))
            v2 : _RESULT = f(MapTreeLeaf_2__get_Value(m2))
            r2 : Optional[MapTreeLeaf_2[_KEY, _RESULT]] = MapTreeModule_map(f, MapTreeNode_2__get_Right(m2))
            return MapTreeNode_2__ctor_Z39DE9543(MapTreeLeaf_2__get_Key(m2), v2, l2, r2, MapTreeNode_2__get_Height(m2))
        
        else: 
            return MapTreeLeaf_2__ctor_5BDDA1(MapTreeLeaf_2__get_Key(m2), f(MapTreeLeaf_2__get_Value(m2)))
        
    
    else: 
        return MapTreeModule_empty()
    


def MapTreeModule_mapiOpt(f: Any, m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> Optional[MapTreeLeaf_2[_KEY, _RESULT]]:
    if m is not None:
        m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
        if isinstance(m2, MapTreeNode_2):
            l2 : Optional[MapTreeLeaf_2[_KEY, _RESULT]] = MapTreeModule_mapiOpt(f, MapTreeNode_2__get_Left(m2))
            v2 : _RESULT = f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
            r2 : Optional[MapTreeLeaf_2[_KEY, _RESULT]] = MapTreeModule_mapiOpt(f, MapTreeNode_2__get_Right(m2))
            return MapTreeNode_2__ctor_Z39DE9543(MapTreeLeaf_2__get_Key(m2), v2, l2, r2, MapTreeNode_2__get_Height(m2))
        
        else: 
            return MapTreeLeaf_2__ctor_5BDDA1(MapTreeLeaf_2__get_Key(m2), f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2)))
        
    
    else: 
        return MapTreeModule_empty()
    


def MapTreeModule_mapi(f: Callable[[_A_, _B_], _C_], m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> Optional[MapTreeLeaf_2[_A_, _C_]]:
    return MapTreeModule_mapiOpt(f, m)


def MapTreeModule_foldBackOpt(f_mut: Any, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]], x_mut: _A_) -> _A_:
    while True:
        (f, m, x) = (f_mut, m_mut, x_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                x_1 : _A_ = MapTreeModule_foldBackOpt(f, MapTreeNode_2__get_Right(m2), x)
                x_2 : _A_ = f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), x_1)
                f_mut = f
                m_mut = MapTreeNode_2__get_Left(m2)
                x_mut = x_2
                continue
            
            else: 
                return f(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), x)
            
        
        else: 
            return x
        
        break


def MapTreeModule_foldBack(f: Callable[[_A_, _B_, _C_], _C_], m: Optional[MapTreeLeaf_2[_A_, _B_]], x: _C_) -> _C_:
    return MapTreeModule_foldBackOpt(f, m, x)


def MapTreeModule_foldOpt(f_mut: Any, x_mut: _A_, m_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]]) -> _A_:
    while True:
        (f, x, m) = (f_mut, x_mut, m_mut)
        if m is not None:
            m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
            if isinstance(m2, MapTreeNode_2):
                f_mut = f
                x_mut = f(MapTreeModule_foldOpt(f, x, MapTreeNode_2__get_Left(m2)), MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
                m_mut = MapTreeNode_2__get_Right(m2)
                continue
            
            else: 
                return f(x, MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2))
            
        
        else: 
            return x
        
        break


def MapTreeModule_fold(f: Callable[[_A_, _B_, _C_], _A_], x: _A_, m: Optional[MapTreeLeaf_2[_B_, _C_]]=None) -> _A_:
    return MapTreeModule_foldOpt(f, x, m)


def MapTreeModule_foldSectionOpt(comparer: IComparer[_KEY], lo: _KEY, hi: _KEY, f: Any, m: Optional[MapTreeLeaf_2[_KEY, _VALUE]], x: _A_) -> _A_:
    def fold_from_to(f_1_mut: Any, m_1_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]], x_1_mut: _B_, comparer: IComparer[_KEY]=comparer, lo: _KEY=lo, hi: _KEY=hi, f: Any=f, m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=m, x: _A_=x) -> _B_:
        while True:
            (f_1, m_1, x_1) = (f_1_mut, m_1_mut, x_1_mut)
            if m_1 is not None:
                m2 : MapTreeLeaf_2[_KEY, _VALUE] = m_1
                if isinstance(m2, MapTreeNode_2):
                    c_lo_key : int = comparer.Compare(lo, MapTreeLeaf_2__get_Key(m2)) or 0
                    c_key_hi : int = comparer.Compare(MapTreeLeaf_2__get_Key(m2), hi) or 0
                    x_2 : _B_ = fold_from_to(f_1, MapTreeNode_2__get_Left(m2), x_1) if (c_lo_key < 0) else x_1
                    x_3 : _B_ = f_1(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), x_2) if ((c_key_hi <= 0) if (c_lo_key <= 0) else False) else x_2
                    if c_key_hi < 0:
                        f_1_mut = f_1
                        m_1_mut = MapTreeNode_2__get_Right(m2)
                        x_1_mut = x_3
                        continue
                    
                    else: 
                        return x_3
                    
                
                elif (comparer.Compare(MapTreeLeaf_2__get_Key(m2), hi) <= 0) if (comparer.Compare(lo, MapTreeLeaf_2__get_Key(m2)) <= 0) else False:
                    return f_1(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2), x_1)
                
                else: 
                    return x_1
                
            
            else: 
                return x_1
            
            break
    
    if comparer.Compare(lo, hi) == 1:
        return x
    
    else: 
        return fold_from_to(f, m, x)
    


def MapTreeModule_foldSection(comparer: IComparer[_KEY], lo: _KEY, hi: _KEY, f: Callable[[_KEY, _A_, _B_], _B_], m: Optional[MapTreeLeaf_2[_KEY, _A_]], x: _B_) -> _B_:
    return MapTreeModule_foldSectionOpt(comparer, lo, hi, f, m, x)


def MapTreeModule_toList(m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> FSharpList[Tuple[_KEY, _VALUE]]:
    def loop(m_1_mut: Optional[MapTreeLeaf_2[_KEY, _VALUE]], acc_mut: FSharpList[Tuple[_KEY, _VALUE]], m: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=m) -> FSharpList[Tuple[_KEY, _VALUE]]:
        while True:
            (m_1, acc) = (m_1_mut, acc_mut)
            if m_1 is not None:
                m2 : MapTreeLeaf_2[_KEY, _VALUE] = m_1
                if isinstance(m2, MapTreeNode_2):
                    m_1_mut = MapTreeNode_2__get_Left(m2)
                    acc_mut = cons((MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2)), loop(MapTreeNode_2__get_Right(m2), acc))
                    continue
                
                else: 
                    return cons((MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2)), acc)
                
            
            else: 
                return acc
            
            break
    
    return loop(m, empty_1())


def MapTreeModule_copyToArray(m: Optional[MapTreeLeaf_2[_A_, _B_]], arr: List[Any], i: int) -> None:
    j : int = i or 0
    def arrow_270(x: _A_, y: _B_, m: Optional[MapTreeLeaf_2[_A_, _B_]]=m, arr: List[Any]=arr, i: int=i) -> None:
        nonlocal j
        arr[j] = (x, y)
        j = (j + 1) or 0
    
    MapTreeModule_iter(arrow_270, m)


def MapTreeModule_toArray(m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> List[Any]:
    n : int = MapTreeModule_size(m) or 0
    res : List[Any] = fill([0] * n, 0, n, (None, None))
    MapTreeModule_copyToArray(m, res, 0)
    return res


def MapTreeModule_ofList(comparer: IComparer[_A_], l: FSharpList[Tuple[_A_, _B_]]) -> Optional[MapTreeLeaf_2[_A_, _B_]]:
    def arrow_271(acc: Optional[MapTreeLeaf_2[_A_, _B_]], tupled_arg: Tuple[_A_, _B_], comparer: IComparer[_A_]=comparer, l: FSharpList[Tuple[_A_, _B_]]=l) -> Optional[MapTreeLeaf_2[_A_, _B_]]:
        return MapTreeModule_add(comparer, tupled_arg[0], tupled_arg[1], acc)
    
    return fold_1(arrow_271, MapTreeModule_empty(), l)


def MapTreeModule_mkFromEnumerator(comparer_mut: IComparer[_A_], acc_mut: Optional[MapTreeLeaf_2[_A_, _B_]], e_mut: IEnumerator[Tuple[_A_, _B_]]) -> Optional[MapTreeLeaf_2[_A_, _B_]]:
    while True:
        (comparer, acc, e) = (comparer_mut, acc_mut, e_mut)
        if e.System_Collections_IEnumerator_MoveNext():
            pattern_input : Tuple[_A_, _B_] = e.System_Collections_Generic_IEnumerator_00601_get_Current()
            comparer_mut = comparer
            acc_mut = MapTreeModule_add(comparer, pattern_input[0], pattern_input[1], acc)
            e_mut = e
            continue
        
        else: 
            return acc
        
        break


def MapTreeModule_ofArray(comparer: IComparer[_KEY], arr: List[Tuple[_KEY, _VALUE]]) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    res : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = MapTreeModule_empty()
    for idx in range(0, (len(arr) - 1) + 1, 1):
        for_loop_var : Tuple[_KEY, _VALUE] = arr[idx]
        res = MapTreeModule_add(comparer, for_loop_var[0], for_loop_var[1], res)
    return res


def MapTreeModule_ofSeq(comparer: IComparer[_KEY], c: IEnumerable[Tuple[_KEY, _VALUE]]) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    if is_array_like(c):
        return MapTreeModule_ofArray(comparer, c)
    
    elif isinstance(c, FSharpList):
        return MapTreeModule_ofList(comparer, c)
    
    else: 
        with get_enumerator(c) as ie:
            return MapTreeModule_mkFromEnumerator(comparer, MapTreeModule_empty(), ie)
    


def expr_272(gen0: TypeInfo, gen1: TypeInfo) -> TypeInfo:
    return record_type("Map.MapTreeModule.MapIterator`2", [gen0, gen1], MapTreeModule_MapIterator_2, lambda: [("stack", list_type(option_type(MapTreeLeaf_2_reflection(gen0, gen1)))), ("started", bool_type)])


class MapTreeModule_MapIterator_2(Record, Generic[_KEY, _VALUE]):
    def __init__(self, stack: FSharpList[Optional[MapTreeLeaf_2[_KEY, _VALUE]]], started: bool) -> None:
        super().__init__()
        self.stack = stack
        self.started = started
    

MapTreeModule_MapIterator_2_reflection = expr_272

def MapTreeModule_collapseLHS(stack_mut: FSharpList[Optional[MapTreeLeaf_2[_KEY, _VALUE]]]) -> FSharpList[Optional[MapTreeLeaf_2[_KEY, _VALUE]]]:
    while True:
        (stack,) = (stack_mut,)
        if not is_empty_1(stack):
            rest : FSharpList[Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = tail(stack)
            m : Optional[MapTreeLeaf_2[_KEY, _VALUE]] = head(stack)
            if m is not None:
                m2 : MapTreeLeaf_2[_KEY, _VALUE] = m
                if isinstance(m2, MapTreeNode_2):
                    stack_mut = of_array_with_tail([MapTreeNode_2__get_Left(m2), MapTreeLeaf_2__ctor_5BDDA1(MapTreeLeaf_2__get_Key(m2), MapTreeLeaf_2__get_Value(m2)), MapTreeNode_2__get_Right(m2)], rest)
                    continue
                
                else: 
                    return stack
                
            
            else: 
                stack_mut = rest
                continue
            
        
        else: 
            return empty_1()
        
        break


def MapTreeModule_mkIterator(m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> MapTreeModule_MapIterator_2[_A_, _B_]:
    return MapTreeModule_MapIterator_2(MapTreeModule_collapseLHS(singleton(m)), False)


def MapTreeModule_notStarted() -> _A_:
    raise Exception("enumeration not started")


def MapTreeModule_alreadyFinished() -> _A_:
    raise Exception("enumeration already finished")


def MapTreeModule_current(i: MapTreeModule_MapIterator_2[_KEY, _VALUE]) -> Any:
    if i.started:
        match_value : FSharpList[Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = i.stack
        if not is_empty_1(match_value):
            if head(match_value) is not None:
                m : MapTreeLeaf_2[_KEY, _VALUE] = head(match_value)
                if isinstance(m, MapTreeNode_2):
                    raise Exception("Please report error: Map iterator, unexpected stack for current")
                
                else: 
                    return (MapTreeLeaf_2__get_Key(m), MapTreeLeaf_2__get_Value(m))
                
            
            else: 
                raise Exception("Please report error: Map iterator, unexpected stack for current")
            
        
        else: 
            return MapTreeModule_alreadyFinished()
        
    
    else: 
        return MapTreeModule_notStarted()
    


def MapTreeModule_moveNext(i: MapTreeModule_MapIterator_2[_KEY, _VALUE]) -> bool:
    if i.started:
        match_value : FSharpList[Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = i.stack
        if not is_empty_1(match_value):
            if head(match_value) is not None:
                m : MapTreeLeaf_2[_KEY, _VALUE] = head(match_value)
                if isinstance(m, MapTreeNode_2):
                    raise Exception("Please report error: Map iterator, unexpected stack for moveNext")
                
                else: 
                    i.stack = MapTreeModule_collapseLHS(tail(match_value))
                    return not is_empty_1(i.stack)
                
            
            else: 
                raise Exception("Please report error: Map iterator, unexpected stack for moveNext")
            
        
        else: 
            return False
        
    
    else: 
        i.started = True
        return not is_empty_1(i.stack)
    


def MapTreeModule_mkIEnumerator(m: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> IEnumerator[Any]:
    i : MapTreeModule_MapIterator_2[_A_, _B_] = MapTreeModule_mkIterator(m)
    class ObjectExpr273(IEnumerator[Any]):
        def System_Collections_Generic_IEnumerator_00601_get_Current(self, m: Optional[MapTreeLeaf_2[_A_, _B_]]=m) -> Any:
            return MapTreeModule_current(i)
        
        def System_Collections_IEnumerator_get_Current(self, m: Optional[MapTreeLeaf_2[_A_, _B_]]=m) -> Any:
            return MapTreeModule_current(i)
        
        def System_Collections_IEnumerator_MoveNext(self, m: Optional[MapTreeLeaf_2[_A_, _B_]]=m) -> bool:
            return MapTreeModule_moveNext(i)
        
        def System_Collections_IEnumerator_Reset(self, m: Optional[MapTreeLeaf_2[_A_, _B_]]=m) -> None:
            nonlocal i
            i = MapTreeModule_mkIterator(m)
        
        def Dispose(self, m: Optional[MapTreeLeaf_2[_A_, _B_]]=m) -> None:
            pass
        
    return ObjectExpr273()


def MapTreeModule_toSeq(s: Optional[MapTreeLeaf_2[_A_, _B_]]=None) -> IEnumerable[Any]:
    def generator(en_1: IEnumerator[Any], s: Optional[MapTreeLeaf_2[_A_, _B_]]=s) -> Optional[Tuple[Any, IEnumerator[Any]]]:
        if en_1.System_Collections_IEnumerator_MoveNext():
            return (en_1.System_Collections_Generic_IEnumerator_00601_get_Current(), en_1)
        
        else: 
            return None
        
    
    return unfold(generator, MapTreeModule_mkIEnumerator(s))


def expr_276(gen0: TypeInfo, gen1: TypeInfo) -> TypeInfo:
    return class_type("Map.FSharpMap", [gen0, gen1], FSharpMap)


class FSharpMap(Generic[_KEY, _VALUE]):
    def __init__(self, comparer: IComparer[_KEY], tree: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> None:
        self.comparer = comparer
        self.tree = tree
    
    def GetHashCode(self) -> int:
        this : FSharpMap[_KEY, _VALUE] = self
        return FSharpMap__ComputeHashCode(this)
    
    def __eq__(self, that: Any=None) -> bool:
        this : FSharpMap[_KEY, _VALUE] = self
        if isinstance(that, FSharpMap):
            with get_enumerator(this) as e1:
                with get_enumerator(that) as e2:
                    def loop(__unit: Any=None) -> bool:
                        m1 : bool = e1.System_Collections_IEnumerator_MoveNext()
                        if m1 == e2.System_Collections_IEnumerator_MoveNext():
                            if not m1:
                                return True
                            
                            else: 
                                e1c : Any = e1.System_Collections_Generic_IEnumerator_00601_get_Current()
                                e2c : Any = e2.System_Collections_Generic_IEnumerator_00601_get_Current()
                                if equals(e1c[1], e2c[1]) if equals(e1c[0], e2c[0]) else False:
                                    return loop()
                                
                                else: 
                                    return False
                                
                            
                        
                        else: 
                            return False
                        
                    
                    loop : Callable[[], bool] = loop
                    return loop()
        
        else: 
            return False
        
    
    def __str__(self) -> str:
        this : FSharpMap[_KEY, _VALUE] = self
        def arrow_274(kv: Any) -> str:
            return format("({0}, {1})", kv[0], kv[1])
        
        return ("map [" + join("; ", map_1(arrow_274, this))) + "]"
    
    @property
    def Symbol_toStringTag(self) -> str:
        return "FSharpMap"
    
    def to_json(self, _key: str) -> Any:
        this : FSharpMap[_KEY, _VALUE] = self
        return Array.from_(this)
    
    def GetEnumerator(self) -> IEnumerator[Any]:
        _ : FSharpMap[_KEY, _VALUE] = self
        return MapTreeModule_mkIEnumerator(_.tree)
    
    def __iter__(self) -> IEnumerator[Any]:
        return to_iterator(self.GetEnumerator())
    
    def System_Collections_IEnumerable_GetEnumerator(self) -> IEnumerator[Any]:
        _ : FSharpMap[_KEY, _VALUE] = self
        return MapTreeModule_mkIEnumerator(_.tree)
    
    def CompareTo(self, obj: Any=None) -> int:
        m : FSharpMap[_KEY, _VALUE] = self
        if isinstance(obj, FSharpMap):
            def arrow_275(kvp1: Any, kvp2: Any) -> int:
                c : int = m.comparer.Compare(kvp1[0], kvp2[0]) or 0
                return c if (c != 0) else compare(kvp1[1], kvp2[1])
            
            return compare_with(arrow_275, m, obj)
        
        else: 
            raise Exception("not comparable\\nParameter name: obj")
        
    
    def System_Collections_Generic_ICollection_00601_Add2B595(self, x: Any) -> None:
        ignore(x)
        raise Exception("Map cannot be mutated")
    
    def System_Collections_Generic_ICollection_00601_Clear(self) -> None:
        raise Exception("Map cannot be mutated")
    
    def System_Collections_Generic_ICollection_00601_Remove2B595(self, x: Any) -> bool:
        ignore(x)
        raise Exception("Map cannot be mutated")
    
    def System_Collections_Generic_ICollection_00601_Contains2B595(self, x: Any) -> bool:
        m : FSharpMap[_KEY, _VALUE] = self
        return equals(FSharpMap__get_Item(m, x[0]), x[1]) if FSharpMap__ContainsKey(m, x[0]) else False
    
    def System_Collections_Generic_ICollection_00601_CopyToZ2E171D71(self, arr: List[Any], i: int) -> None:
        m : FSharpMap[_KEY, _VALUE] = self
        MapTreeModule_copyToArray(m.tree, arr, i)
    
    def System_Collections_Generic_ICollection_00601_get_IsReadOnly(self) -> bool:
        return True
    
    def System_Collections_Generic_ICollection_00601_get_Count(self) -> int:
        m : FSharpMap[_KEY, _VALUE] = self
        return FSharpMap__get_Count(m)
    
    def System_Collections_Generic_IReadOnlyCollection_00601_get_Count(self) -> int:
        m : FSharpMap[_KEY, _VALUE] = self
        return FSharpMap__get_Count(m)
    
    @property
    def size(self) -> int:
        m : FSharpMap[_KEY, _VALUE] = self
        return FSharpMap__get_Count(m)
    
    def clear(self) -> None:
        raise Exception("Map cannot be mutated")
    
    def delete(self, _arg1: Optional[_KEY]=None) -> bool:
        raise Exception("Map cannot be mutated")
        return False
    
    def entries(self) -> IEnumerable[Tuple[_KEY, _VALUE]]:
        m : FSharpMap[_KEY, _VALUE] = self
        def mapping(p: Any) -> Tuple[_KEY, _VALUE]:
            return (p[0], p[1])
        
        return map_1(mapping, m)
    
    def __getitem__(self, k: Optional[_KEY]=None) -> _VALUE:
        m : FSharpMap[_KEY, _VALUE] = self
        return FSharpMap__get_Item(m, k)
    
    def has(self, k: Optional[_KEY]=None) -> bool:
        m : FSharpMap[_KEY, _VALUE] = self
        return FSharpMap__ContainsKey(m, k)
    
    def keys(self) -> IEnumerable[_KEY]:
        m : FSharpMap[_KEY, _VALUE] = self
        def mapping(p: Any) -> _KEY:
            return p[0]
        
        return map_1(mapping, m)
    
    def __setitem__(self, k: _KEY, v: _VALUE) -> Map_2[_KEY, _VALUE]:
        m : FSharpMap[_KEY, _VALUE] = self
        raise Exception("Map cannot be mutated")
        return m
    
    def values(self) -> IEnumerable[_VALUE]:
        m : FSharpMap[_KEY, _VALUE] = self
        def mapping(p: Any) -> _VALUE:
            return p[1]
        
        return map_1(mapping, m)
    
    def for_each(self, f: Callable[[_VALUE, _KEY, Map_2[_KEY, _VALUE]], None], this_arg: Optional[Any]=None) -> None:
        m : FSharpMap[_KEY, _VALUE] = self
        def action(p: Any) -> None:
            f(p[1], p[0], m)
        
        iterate_1(action, m)
    

FSharpMap_reflection = expr_276

def FSharpMap__ctor(comparer: IComparer[_KEY], tree: Optional[MapTreeLeaf_2[_KEY, _VALUE]]=None) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap(comparer, tree)


def FSharpMap_Empty(comparer: IComparer[_KEY]) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap__ctor(comparer, MapTreeModule_empty())


def FSharpMap__get_Comparer(m: FSharpMap[_KEY, _VALUE]) -> IComparer[_KEY]:
    return m.comparer


def FSharpMap__get_Tree(m: FSharpMap[_KEY, _VALUE]) -> Optional[MapTreeLeaf_2[_KEY, _VALUE]]:
    return m.tree


def FSharpMap__Add(m: FSharpMap[_KEY, _VALUE], key: _KEY, value: _VALUE) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap__ctor(m.comparer, MapTreeModule_add(m.comparer, key, value, m.tree))


def FSharpMap__Change(m: FSharpMap[_KEY, _VALUE], key: _KEY, f: Callable[[Optional[_VALUE]], Optional[_VALUE]]) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap__ctor(m.comparer, MapTreeModule_change(m.comparer, key, f, m.tree))


def FSharpMap__get_IsEmpty(m: FSharpMap[_KEY, _VALUE]) -> bool:
    return m.tree is None


def FSharpMap__get_Item(m: FSharpMap[_KEY, _VALUE], key: _KEY) -> _VALUE:
    return MapTreeModule_find(m.comparer, key, m.tree)


def FSharpMap__TryPick(m: FSharpMap[_KEY, _VALUE], f: Callable[[_KEY, _VALUE], Optional[_A_]]) -> Optional[_A_]:
    return MapTreeModule_tryPick(f, m.tree)


def FSharpMap__Exists(m: FSharpMap[_KEY, _VALUE], predicate: Callable[[_KEY, _VALUE], bool]) -> bool:
    return MapTreeModule_exists(predicate, m.tree)


def FSharpMap__Filter(m: FSharpMap[_KEY, _VALUE], predicate: Callable[[_KEY, _VALUE], bool]) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap__ctor(m.comparer, MapTreeModule_filter(m.comparer, predicate, m.tree))


def FSharpMap__ForAll(m: FSharpMap[_KEY, _VALUE], predicate: Callable[[_KEY, _VALUE], bool]) -> bool:
    return MapTreeModule_forall(predicate, m.tree)


def FSharpMap__Fold(m: FSharpMap[_KEY, _VALUE], f: Callable[[_KEY, _VALUE, _A_], _A_], acc: _A_) -> _A_:
    return MapTreeModule_foldBack(f, m.tree, acc)


def FSharpMap__FoldSection(m: FSharpMap[_KEY, _VALUE], lo: _KEY, hi: _KEY, f: Callable[[_KEY, _VALUE, _Z], _Z], acc: _Z) -> _Z:
    return MapTreeModule_foldSection(m.comparer, lo, hi, f, m.tree, acc)


def FSharpMap__Iterate(m: FSharpMap[_KEY, _VALUE], f: Callable[[_KEY, _VALUE], None]) -> None:
    MapTreeModule_iter(f, m.tree)


def FSharpMap__MapRange(m: FSharpMap[_KEY, _VALUE], f: Callable[[_VALUE], _RESULT]) -> FSharpMap[_KEY, _RESULT]:
    return FSharpMap__ctor(m.comparer, MapTreeModule_map(f, m.tree))


def FSharpMap__Map(m: FSharpMap[_KEY, _VALUE], f: Callable[[_KEY, _VALUE], _B]) -> FSharpMap[_KEY, _B]:
    return FSharpMap__ctor(m.comparer, MapTreeModule_mapi(f, m.tree))


def FSharpMap__Partition(m: FSharpMap[_KEY, _VALUE], predicate: Callable[[_KEY, _VALUE], bool]) -> Tuple[FSharpMap[_KEY, _VALUE], FSharpMap[_KEY, _VALUE]]:
    pattern_input : Tuple[Optional[MapTreeLeaf_2[_KEY, _VALUE]], Optional[MapTreeLeaf_2[_KEY, _VALUE]]] = MapTreeModule_partition(m.comparer, predicate, m.tree)
    return (FSharpMap__ctor(m.comparer, pattern_input[0]), FSharpMap__ctor(m.comparer, pattern_input[1]))


def FSharpMap__get_Count(m: FSharpMap[_KEY, _VALUE]) -> int:
    return MapTreeModule_size(m.tree)


def FSharpMap__ContainsKey(m: FSharpMap[_KEY, _VALUE], key: _KEY) -> bool:
    return MapTreeModule_mem(m.comparer, key, m.tree)


def FSharpMap__Remove(m: FSharpMap[_KEY, _VALUE], key: _KEY) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap__ctor(m.comparer, MapTreeModule_remove(m.comparer, key, m.tree))


def FSharpMap__TryGetValue(_: FSharpMap[_KEY, _VALUE], key: _KEY, value: FSharpRef[_VALUE]) -> bool:
    match_value : Optional[_VALUE] = MapTreeModule_tryFind(_.comparer, key, _.tree)
    if match_value is None:
        return False
    
    else: 
        v : _VALUE = value_1(match_value)
        value.contents = v
        return True
    


def FSharpMap__get_Keys(__: FSharpMap[_KEY, _VALUE]) -> ICollection[_KEY]:
    def mapping(kvp: Any, __: FSharpMap[_KEY, _VALUE]=__) -> _KEY:
        return kvp[0]
    
    return map_2(mapping, MapTreeModule_toArray(__.tree), None)


def FSharpMap__get_Values(__: FSharpMap[_KEY, _VALUE]) -> ICollection[_VALUE]:
    def mapping(kvp: Any, __: FSharpMap[_KEY, _VALUE]=__) -> _VALUE:
        return kvp[1]
    
    return map_2(mapping, MapTreeModule_toArray(__.tree), None)


def FSharpMap__TryFind(m: FSharpMap[_KEY, _VALUE], key: _KEY) -> Optional[_VALUE]:
    return MapTreeModule_tryFind(m.comparer, key, m.tree)


def FSharpMap__ToList(m: FSharpMap[_KEY, _VALUE]) -> FSharpList[Tuple[_KEY, _VALUE]]:
    return MapTreeModule_toList(m.tree)


def FSharpMap__ToArray(m: FSharpMap[_KEY, _VALUE]) -> List[Any]:
    return MapTreeModule_toArray(m.tree)


def FSharpMap__ComputeHashCode(this: FSharpMap[_KEY, _VALUE]) -> int:
    def combine_hash(x: int, y: int, this: FSharpMap[_KEY, _VALUE]=this) -> int:
        return ((x << 1) + y) + 631
    
    res : int = 0
    with get_enumerator(this) as enumerator:
        while enumerator.System_Collections_IEnumerator_MoveNext():
            active_pattern_result6638 : Tuple[_KEY, _VALUE] = enumerator.System_Collections_Generic_IEnumerator_00601_get_Current()
            res = combine_hash(res, structural_hash(active_pattern_result6638[0])) or 0
            res = combine_hash(res, structural_hash(active_pattern_result6638[1])) or 0
    return res


def is_empty(table: FSharpMap[_A_, _B_]) -> bool:
    return FSharpMap__get_IsEmpty(table)


def add(key: _A_, value: _B_, table: FSharpMap[_A_, _B_]) -> FSharpMap[_A_, _B_]:
    return FSharpMap__Add(table, key, value)


def change(key: _A_, f: Callable[[Optional[_B_]], Optional[_B_]], table: FSharpMap[_A_, _B_]) -> FSharpMap[_A_, _B_]:
    return FSharpMap__Change(table, key, f)


def find(key: _A_, table: FSharpMap[_A_, _B_]) -> _B_:
    return FSharpMap__get_Item(table, key)


def try_find(key: _A_, table: FSharpMap[_A_, _B_]) -> Optional[_B_]:
    return FSharpMap__TryFind(table, key)


def remove(key: _A_, table: FSharpMap[_A_, _B_]) -> FSharpMap[_A_, _B_]:
    return FSharpMap__Remove(table, key)


def contains_key(key: _A_, table: FSharpMap[_A_, _B_]) -> bool:
    return FSharpMap__ContainsKey(table, key)


def iterate(action: Callable[[_A_, _B_], None], table: FSharpMap[_A_, _B_]) -> None:
    FSharpMap__Iterate(table, action)


def try_pick(chooser: Callable[[_A_, _B_], Optional[_C_]], table: FSharpMap[_A_, _B_]) -> Optional[_C_]:
    return FSharpMap__TryPick(table, chooser)


def pick(chooser: Callable[[_A_, _B_], Optional[_C_]], table: FSharpMap[_A_, _B_]) -> _C_:
    match_value : Optional[_C_] = try_pick(chooser, table)
    if match_value is not None:
        return value_1(match_value)
    
    else: 
        raise Exception()
    


def exists(predicate: Callable[[_A_, _B_], bool], table: FSharpMap[_A_, _B_]) -> bool:
    return FSharpMap__Exists(table, predicate)


def filter(predicate: Callable[[_A_, _B_], bool], table: FSharpMap[_A_, _B_]) -> FSharpMap[_A_, _B_]:
    return FSharpMap__Filter(table, predicate)


def partition(predicate: Callable[[_A_, _B_], bool], table: FSharpMap[_A_, _B_]) -> Tuple[FSharpMap[_A_, _B_], FSharpMap[_A_, _B_]]:
    return FSharpMap__Partition(table, predicate)


def for_all(predicate: Callable[[_A_, _B_], bool], table: FSharpMap[_A_, _B_]) -> bool:
    return FSharpMap__ForAll(table, predicate)


def map(mapping: Callable[[_A_, _B_], _C_], table: FSharpMap[_A_, _B_]) -> FSharpMap[_A_, _C_]:
    return FSharpMap__Map(table, mapping)


def fold(folder: Callable[[_STATE, _KEY, _T], _STATE], state: _STATE, table: FSharpMap[_KEY, _T]) -> _STATE:
    return MapTreeModule_fold(folder, state, FSharpMap__get_Tree(table))


def fold_back(folder: Callable[[_KEY, _T, _STATE], _STATE], table: FSharpMap[_KEY, _T], state: _STATE) -> _STATE:
    return MapTreeModule_foldBack(folder, FSharpMap__get_Tree(table), state)


def to_seq(table: FSharpMap[_A_, _B_]) -> IEnumerable[Tuple[_A_, _B_]]:
    def mapping(kvp: Any, table: FSharpMap[_A_, _B_]=table) -> Tuple[_A_, _B_]:
        return (kvp[0], kvp[1])
    
    return map_1(mapping, table)


def find_key(predicate: Callable[[_A_, _B_], bool], table: FSharpMap[_A_, _B_]) -> _A_:
    def chooser(kvp: Any, predicate: Callable[[_A_, _B_], bool]=predicate, table: FSharpMap[_A_, _B_]=table) -> Optional[_A_]:
        k : _A_ = kvp[0]
        if predicate(k, kvp[1]):
            return some(k)
        
        else: 
            return None
        
    
    return pick_1(chooser, table)


def try_find_key(predicate: Callable[[_A_, _B_], bool], table: FSharpMap[_A_, _B_]) -> Optional[_A_]:
    def chooser(kvp: Any, predicate: Callable[[_A_, _B_], bool]=predicate, table: FSharpMap[_A_, _B_]=table) -> Optional[_A_]:
        k : _A_ = kvp[0]
        if predicate(k, kvp[1]):
            return some(k)
        
        else: 
            return None
        
    
    return try_pick_1(chooser, table)


def of_list(elements: FSharpList[Tuple[_KEY, _VALUE]], comparer: IComparer[_KEY]) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap__ctor(comparer, MapTreeModule_ofSeq(comparer, elements))


def of_seq(elements: IEnumerable[Tuple[_T, _A_]], comparer: IComparer[_T]) -> FSharpMap[_T, _A_]:
    return FSharpMap__ctor(comparer, MapTreeModule_ofSeq(comparer, elements))


def of_array(elements: List[Tuple[_KEY, _VALUE]], comparer: IComparer[_KEY]) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap__ctor(comparer, MapTreeModule_ofSeq(comparer, elements))


def to_list(table: FSharpMap[_A_, _B_]) -> FSharpList[Tuple[_A_, _B_]]:
    return FSharpMap__ToList(table)


def to_array(table: FSharpMap[_A_, _B_]) -> List[Any]:
    return FSharpMap__ToArray(table)


def keys(table: FSharpMap[_K, _V]) -> ICollection[_K]:
    return FSharpMap__get_Keys(table)


def values(table: FSharpMap[_K, _V]) -> ICollection[_V]:
    return FSharpMap__get_Values(table)


def empty(comparer: IComparer[_KEY]) -> FSharpMap[_KEY, _VALUE]:
    return FSharpMap_Empty(comparer)


def count(table: FSharpMap[_A_, _B_]) -> int:
    return FSharpMap__get_Count(table)


