[Haskell-cafe] [Haskell-beginners] Tying the knot

Antoine Latter aslatter at gmail.com
Thu Dec 30 04:08:29 CET 2010


On Wed, Dec 29, 2010 at 7:22 PM, aditya siram <aditya.siram at gmail.com> wrote:
> My brain turns into strange braid when I see this kind of thing. I
> don't quite understand it and I've never used it in real world code
> but I'll try and explain anyway. Caveat emptor.
>

Once when I was parsing a group of source files into an AST, the
source files included 'copy' directives that allowed pieces of syntax
to be a clone of some other piece of syntax - even across source
files.

So I did the whole process of parsing in the Reader monad, which was
parametrized over the result of parsing all of the files. When I hit a
copy directive, I simply called 'ask' and looked up the element I
wanted to copy.

It doesn't allow for separate processing of source files, but I didn't
really need it.

Antoine

> First forget about 'labelLeaves' and think a function that only
> returned the leaf count:
>  count :: Tree a -> Int
>  count tree = c
>     where
>     c = count' tree
>
>     count' (Branch a b) = na+nb
>         where
>         na = count' a
>         nb = count' b
>     count' (Leaf _)  = 1
>
>> count $ Branch (Leaf "hello") (Leaf "world")
> 2
>
> Now look at 'n' and imagine it was a memory location. Mentally
> substitute some hex address (like 0x0000) if it makes it easier.
> Here's what the function looks like now:
>
>  labelLeaves :: Tree a -> Tree Int
>  labelLeaves tree = tree'
>      where
>      (0x0000, tree') = label 0x0000 tree  -- n is both result and argument!
>
>      label 0x0000 (Branch a b) = (na+nb, Branch a' b')
>          where
>          (na,a') = label 0x0000 a
>          (nb,b') = label 0x0000 b
>      label 0x0000 (Leaf _)     = (1, Leaf 0x0000)
>
> So if labelLeaves is given (Branch (Leaf "hello") (Leaf "world")) as
> an argument, and we continue to think of 'n' as a memory location the
> function returns something like:
> (Branch (Leaf 0x0000) (Leaf 0x0000))
>
> The part of the function where the leaves are counted up is exactly
> like my 'count' example above, but when the function is done instead
> of just returning it this line:
>  (n,tree') = label n tree
> assigns the final count to 'n'. If 'n' is a memory location the final
> leaf count would be sitting in 0x0000. Subbing the value at that
> location into the result we get:
> (Branch (Leaf 2) (Leaf 2))
>
>
> -deech
>
> On Wed, Dec 29, 2010 at 4:52 PM, Patrick LeBoutillier
> <patrick.leboutillier at gmail.com> wrote:
>> Heinrich,
>>
>>> A canonical example is the following solution to the problem of labeling all
>>> the leaves in a tree with the total leaf count:
>>>
>>>    data Tree a = Branch (Tree a) (Tree a) | Leaf a
>>>
>>>    labelLeaves :: Tree a -> Tree Int
>>>    labelLeaves tree = tree'
>>>        where
>>>        (n, tree') = label n tree  -- n is both result and argument!
>>>
>>>        label n (Branch a b) = (na+nb, Branch a' b')
>>>            where
>>>            (na,a') = label n a
>>>            (nb,b') = label n b
>>>        label n (Leaf _)     = (1, Leaf n)
>>>
>>
>> This looks completely freaky to me... how does it work? Is it the
>> laziness that allows the sum to be calculated first while preserving
>> the structure (as thunks?), and then once the value of n is known it
>> is propagated back down the tree and the actual tree values
>> constructed? Anyways this is really amazing to my newbie eyes...
>>
>> Patrick
>> --
>> =====================
>> Patrick LeBoutillier
>> Rosemère, Québec, Canada
>>
>> _______________________________________________
>> Beginners mailing list
>> Beginners at haskell.org
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>
> _______________________________________________
> Beginners mailing list
> Beginners at haskell.org
> http://www.haskell.org/mailman/listinfo/beginners
>



More information about the Haskell-Cafe mailing list