Re: [Haskell-cafe] Re: ambiguous partially defined type problem

2006-09-15 Thread Maarten

Dear Brian,

Maarten wrote:

Brian Hulley wrote:

Alternatively, you could wrap the custom part within the node as in:

   data Node = forall cust. ICustom cust = Node cust Common

   getCommon :: Node - Common
   getCommon (Node cust com) = com

Thanks. This really helped. The main thing (I think) that you put the 
custom part behind an interface. After this I separated the custom and 
common part of two 'piggy bagged' state transformers, so one can access 
the functionality separately. The state transformers made into active 
object by putting them behind a channel in a separate thread and one can 
invoke actions by writing to the channel. The common functionality 
provides the connections between the active objects. In this way I would 
like to create some sort of 'agent' structure, that receive message and 
process them in their own thread. So far this works quite neat. Wonder 
if this is they way to go though...
Only update (see code below) is a bit ugly (I have no idea why I need 
fixCastUpdate) and Node itself is probably not necessary, so one level 
of indirection could be removed. Rest is quite straight forward.

Thanks again.

Maarten


... (imports)


data Node = forall cust. (ICustom cust) = Node cust
   deriving (Typeable)

instance Show Node where-- just for debugging
   show (Node a) = Node ( ++ show a ++ )

class (Show a, Typeable a) = ICustom a where
   getVal :: forall b cust. (Typeable b, ICustom cust) = a - (cust - 
b) - Maybe b

   getVal a f = case cast a of
   Nothing - Nothing
   Just cust - Just (f cust)
--update :: oif - (forall a. (ObjectIFace a) = a - a) - IO oif
   update :: a - (forall b. (ICustom b) = b - b) - a
   update a f = f a


instance ICustom Node where
   getVal (Node n) f = getVal n f
   update (Node n) f = Node (update n f)

type NodeState a = StateT Node (StateT Common IO) a

type Connection = Chan (NodeState ())
type Connections = [Connection]
instance Show Connection where
   show o = Chan (StateT Node (StateT Common IO) ())
  
-- common part

data Common = Common { uid::Integer, connections::Connections }
   deriving (Show,Typeable)

-- custom data
data Custom = Custom { val::Integer }
   deriving (Show,Typeable)

instance ICustom Custom where

data Custom2 = Custom2 { val2::Integer }
   deriving (Show,Typeable)

instance ICustom Custom2 where

-- some function to use common functionality
uidM :: NodeState Integer
uidM = lift $ gets uid

addNodeM :: Connection - NodeState ()
addNodeM n = lift $ modify (\s - addNode s n)
   where
   addNode (Common i ns) nn = (Common i (nn:ns))

getNodeM :: Integer - NodeState Connection
getNodeM i = do
   s - lift $ get
   return (getNode s i)
   where
   getNode (Common _ ns) i = (ns!!(fromInteger i))

getValM f = do
   s - get
   return (getVal s f)

updateM :: forall a b. (ICustom a, ICustom b) = (a - b) - NodeState ()
updateM f = do
   s - get
   let s' = update s (fixCastUpdate f)
   put s'
  
fixCastUpdate f st =

   case (cast st) of
   Nothing - st
   Just es - case cast (f es) of
   Nothing - st
   Just g - g

getStateM = get
  


-- function to create active node functionality
action [] = return ()
action (e:es) = do
   e
   s - get-- just for debugging
   lift $ lift $ putStrLn $ show s
   action es

newBaseState = do
   uid - newUnique   
   return (Common ((toInteger .hashUnique) uid) [])


initAction list state = do
   bs - newBaseState
   execStateT (execStateT (action list) state) bs
   return ()

send chan action = writeChan chan action

sync chan f = do
   mv - newEmptyMVar
   send chan (f' mv)
   a - takeMVar mv
   return a
   where
   f' mv = do
   a - f
   lift $ lift $ putMVar mv a
  
newActiveObject action state = do

   chan - newChan
   cs - getChanContents chan
   forkIO (action cs state)
   return chan
  
-- example

main = do
   let n1 = Node (Custom 5)
   let n2 = Node (Custom2 6)
   let n3 = Node (Custom2 7)

   chan - newActiveObject initAction n1
   chan2 - newActiveObject initAction n3

   let l = [chan, chan2]
   mapM_ (\ch - send ch (addNodeM chan)) l
   mapM_ (\ch - send ch (addNodeM chan2)) l

   r - mapM (\ch - sync ch (getNodeM 0)) l
   putStrLn $ r: ++ show r
   r2 - mapM (\ch - sync ch (uidM)) l
   putStrLn $ r2: ++ show r2
  
   r3 - mapM (\ch - sync ch (getValM val)) l

   putStrLn $ r3: ++ show r3
  
   mapM_ (\ch - send ch (updateM (\s - s { val2 = 100 }))) l

   r5 - mapM (\ch - sync ch (getStateM)) l
   putStrLn $ r5: ++ show r5

   getChar   
   return ()






___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: ambiguous partially defined type problem

2006-09-15 Thread Brian Hulley

Maarten wrote:

Only update (see code below) is a bit ugly (I have no idea why I need
fixCastUpdate)
class (Show a, Typeable a) = ICustom a where

  [snip]

   update :: a - (forall b. (ICustom b) = b - b) - a
   update a f = f a

instance ICustom Node where
   getVal (Node n) f = getVal n f
   update (Node n) f = Node (update n f)

updateM :: forall a b. (ICustom a, ICustom b) = (a - b) -
NodeState () updateM f = do
   s - get
   let s' = update s (fixCastUpdate f)
   put s'


Hi Maarten -
Looking at this again, I wonder if the following changes would work:

   -- this change is not strictly necessary
   update :: a - (a - a) - a

   updateM :: (forall a. ICustom a = a - a) - NodeState ()
   updateM f = do
   s - get
   let s' = update s f
   put s'

I think the reason why fixCastUpdate was needed in your original definition 
of updateM is because the type of f seems to be too general (a-b) compared 
to the type of f in the update method of ICustom (b-b)


Regards, Brian.
--
Logic empowers us and Love gives us purpose.
Yet still phantoms restless for eras long past,
congealed in the present in unthought forms,
strive mightily unseen to destroy us.

http://www.metamilk.com 


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


Re: [Haskell-cafe] Re: ambiguous partially defined type problem

2006-09-15 Thread Brian Hulley

Brian Hulley wrote:

   -- this change is not strictly necessary
   update :: a - (a - a) - a


Sorry - I just looked again at the instance decl for Node, so the above 
change should not be made.


Apologies for the multiple posts, I must try to think more before clicking 
send ;-)


Regards, Brian. 


___
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe