8

As explained on my previous question, it is impossible to differ two graphs made using the tying the knot strategy if you don't have some kind of unique label on your nodes. Using a two-edged graph as an example:

data Node = Node Int Node Node

square = a where
    a = Node 0 b c
    b = Node 1 a d
    c = Node 2 a d
    d = Node 3 b c

Writing square that way is a little inconvenient and error-prone due to the need of manually writing labels. That kind of pattern would usually call for a monad:

square = do
    a <- Node b c
    b <- Node a d
    c <- Node a d
    d <- Node b c
    return a

But this also can't be done since monads are sequential. Is there any convenient way to write tying-the-knot graphs?

Community
  • 1
  • 1
MaiaVictor
  • 45,122
  • 42
  • 127
  • 254
  • GIven [my other answer](http://stackoverflow.com/a/33337598/477476), maybe for your particular use case, just tying the knot might be the convenient way! – Cactus Oct 26 '15 at 02:31

1 Answers1

10
{-# LANGUAGE RecursiveDo #-}

import Control.Monad.State

type Intividual a = State Int a

data Node = Node Int Node Node

newNode :: Node -> Node -> Intividual Node
newNode a b = state $ \i -> (Node i a b, succ i)

square :: Node
square = (`evalState`0) $ mdo
   a <- newNode b c
   b <- newNode a d
   c <- newNode a d
   d <- newNode b c
   return a
leftaroundabout
  • 101,764
  • 3
  • 156
  • 291
  • `RecursiveDo`, okay, I think I've heard about that someday. Thanks for your answer... can I edit a brief explanation on it? – MaiaVictor Oct 16 '15 at 01:04