[Haskell-beginners] Tying the knot
Heinrich Apfelmus
apfelmus at quantentunnel.de
Wed Dec 29 13:49:34 CET 2010
Alex Rozenshteyn wrote:
> I'm trying to understand the technique referred to as "tying the knot", but
> documentation on the internet seems to be much sparser and more obtuse than
> I like.
>
> So I'm asking here.
>
> As far as I understand, "tying the knot" refers to a way of using laziness
> to implement something like references in a purely functional way.
Not really.
"Tying the knot" refers to writing a seemingly circular program, where
the result of a function is used as argument to the very same function.
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)
In some cases, this be used to implement read-only doubly-linked lists
and other things that seem to require references, but not everything
involving references can be solved by tying a knot; in particular, the
references will be read-only.
(Feel free to put my blurb above on the HaskellWiki.)
> I'm trying to write a toy simulation:
> I have a population :: [Person]
> I want to collect a random subset of possible pairs of distinct people.
> So I go to each person in the population and select a subset of the people
> after him/her in the list; these are pairs in which s/he is the first
> element.
>
> I want to then be able to ask for all pairs in which a person is the first
> or the second element. I could give each person a unique id, but it seems
> like tying the knot is a valid way to implement this.
This situation doesn't have anything to do with tying the knot. After
all, how do you distinguish persons in the first place? You probably
already gave the unique IDs. Then, it's simply a matter of applying the
function
filter (\(x,y) -> x == p || y == p)
where p is the person you are looking for.
Regards,
Heinrich Apfelmus
--
http://apfelmus.nfshost.com
More information about the Beginners
mailing list