assembleShellGroupCollect :: GroupID -> [Shell (Grp a) (Val b)] -> Shell (Grp a) (Grp b)
assembleShellGroupCollect gid shells =
    Shell (ActorGroup gid)
          (RecvReduce $ getRecv =<< shells)
          (SendGrp    $ map getSend shells)
  where
    getRecv :: Shell (Grp a) b -> [(SendPort Int, SendPort a)]
    getRecv (Shell _ (RecvReduce ch) _) = ch
    getSend :: Shell a (Val b) -> SendPort (Dest b)
    getSend (Shell _ _ (SendVal ch)) = ch


-- | Start group of collector processes
assembleShellGroupCollect :: GroupID -> [Shell (Grp a) (Val b)] -> Shell (Grp a) (Grp b)
assembleShellGroupCollect gid shells =
    Shell (ActorGroup gid)
          (RecvReduce $ getRecv =<< shells)
          (SendGrp    $ map getSend shells)
  where
    getRecv :: Shell (Grp a) b -> [(SendPort Int, SendPort a)]
    getRecv (Shell _ (RecvReduce ch) _) = ch
    getSend :: Shell a (Val b) -> SendPort (Dest b)
    getSend (Shell _ _ (SendVal ch)) = ch


-- | Start group of collector processes
assembleShellGroupCollect gid shells =
    Shell (ActorGroup gid)
          (RecvReduce $ getRecv =<< shells)
          (SendGrp    $ map getSend shells)
  where
    getRecv :: Shell (Grp a) b -> [(SendPort Int, SendPort a)]
    getRecv (Shell _ (RecvReduce ch) _) = ch
    getSend :: Shell a (Val b) -> SendPort (Dest b)
    getSend (Shell _ _ (SendVal ch)) = ch


-- | Start group of collector processes