assembleShellGroup :: GroupID -> [Shell (Val a) (Val b)] -> Shell (Scatter a) (Grp b)
assembleShellGroup gid shells =
    Shell (ActorGroup gid)
          (RecvGrp $ map getRecv shells)
          (SendGrp $ map getSend shells)
  where
    getRecv :: Shell (Val a) b -> SendPort a
    getRecv (Shell _ (RecvVal ch) _) = ch
    getRecv _ = error "assembleShellGroup: unexpected type of shell process"
    getSend :: Shell a (Val b) -> SendPort (Dest b)
    getSend (Shell _ _ (SendVal ch)) = ch


-- | Start group of processes where we have more tasks then processes.
assembleShellGroup :: GroupID -> [Shell (Val a) (Val b)] -> Shell (Scatter a) (Grp b)
assembleShellGroup gid shells =
    Shell (ActorGroup gid)
          (RecvGrp $ map getRecv shells)
          (SendGrp $ map getSend shells)
  where
    getRecv :: Shell (Val a) b -> SendPort a
    getRecv (Shell _ (RecvVal ch) _) = ch
    getRecv _ = error "assembleShellGroup: unexpected type of shell process"
    getSend :: Shell a (Val b) -> SendPort (Dest b)
    getSend (Shell _ _ (SendVal ch)) = ch


-- | Start group of processes where we have more tasks then processes.
assembleShellGroup gid shells =
    Shell (ActorGroup gid)
          (RecvGrp $ map getRecv shells)
          (SendGrp $ map getSend shells)
  where
    getRecv :: Shell (Val a) b -> SendPort a
    getRecv (Shell _ (RecvVal ch) _) = ch
    getRecv _ = error "assembleShellGroup: unexpected type of shell process"
    getSend :: Shell a (Val b) -> SendPort (Dest b)
    getSend (Shell _ _ (SendVal ch)) = ch


-- | Start group of processes where we have more tasks then processes.