Esempio n. 1
0
        // Here's a helper that composes UpdateState with Leaf and
        // Branch in the original unlabeled tree. This looks very
        // hairy in C#, but in Haskell it's quite short. Here's what
        // we do with leaves:
        //
        // > mkm :: Tr anytype -> Labeled (Lt anytype)
        // > mkm (Lf x)
        // >   = do n <- updateState  -- call updateState; "n" is of type "S"
        // >        return (Lf (n,x)) -- "return" does the heavy lifting
        // >                          --  of creating the Monad from a value.
        //
        // The "do" notation is just Haskell syntactic sugar for
        // precisely the following call of @bind:
        //
        // updateState >>= \n -> return (Lf (n, x))
        //
        // which says "call update state, which returns an instance of
        // the state monad, then @bind it to the variable n in a
        // function that returns a leaf node labeled by the given
        // state value." We translate this directly into C# below.
        //
        // The Branch case is a trivial recursion. Notice that
        // updateState only gets called on leaves.
        //
        // > mkm (Br l r)
        // >   = do l' <- mkm l
        // >        r' <- mkm r
        // >        return (Br l' r')
        //
        // Notice this is private:

        private static SM <Tr <Scp <a> > > MkM <a>(Tr <a> t)
        {
            if (t is Lf <a> )
            {
                // Call UpdateState to get an instance of
                // SM<int>. Shove it (@bind it) through a lambda
                // expression that converts ints to SM<Tr<Scp<a>>
                // using the "closed-over" contents from the input
                // Leaf node:

                var lf = (t as Lf <a>);

                return(SM <int> .@bind
                           (UpdateState(),
                           (n => SM <Tr <Scp <a> > > .@return
                                (new Lf <Scp <a> >
                {
                    contents = new Scp <a>
                    {
                        label = n,
                        lcpContents = lf.contents
                    }
                }
                                )
                           )
                           ));
            }
            else if (t is Br <a> )
            {
                var br       = (t as Br <a>);
                var oldleft  = br.left;
                var oldright = br.right;

                return(SM <Tr <Scp <a> > > .@bind
                           (MkM <a>(oldleft),
                           (newleft => SM <Tr <Scp <a> > > .@bind
                                (MkM <a>(oldright),
                                (newright => SM <Tr <Scp <a> > > .@return
                                     (new Br <Scp <a> >
                {
                    left = newleft,
                    right = newright
                }
                                     )
                                )
                                )
                           )
                           ));
            }
            else
            {
                throw new Exception("MakeMonad/MLabel: impossible tree subtype");
            }
        }