 @MPI_IDENT@, @MPI_CONGRUENT@, @MPI_SIMILAR@ and @MPI_UNEQUAL@.
 
 Those are used to compare communicators (f.e. 'commCompare') and
-process groups (f.e. 'groupCompare').
+process groups (f.e. 'groupCompare'). Refer to those
+functions for description of comparison rules.
 -}
 {# enum ComparisonResult {underscoreToCase} deriving (Eq,Ord,Show) #}
 
--- | Which Haskell type will be used as @Comm@ depends on the MPI
+-- Which Haskell type will be used as Comm depends on the MPI
 -- implementation that was selected during compilation. It could be
--- @CInt@, @Ptr ()@, @Ptr CInt@ or something else.
+-- CInt, Ptr (), Ptr CInt or something else.
 type MPIComm = {# type MPI_Comm #}
+
+{- | Abstract type representing MPI communicator handle. Different MPI
+   implementations use different C types to implement this, so
+   concrete Haskell type behind @Comm@ is hidden from user.
+
+   In any MPI program you have predefined communicator 'commWorld'
+   which includes all running processes. You could create new
+   communicators with TODO
+-}
 newtype Comm = MkComm { fromComm :: MPIComm }
 foreign import ccall "&mpi_comm_world" commWorld_ :: Ptr MPIComm
 foreign import ccall "&mpi_comm_self" commSelf_ :: Ptr MPIComm

{# fun unsafe Op_create as ^
              {castFunPtr `FunPtr (Ptr t -> Ptr t -> Ptr CInt -> Ptr Datatype -> IO ())', cFromEnum `Bool', alloca- `Operation' peekOperation*} -> `()' checkError*- #}
{# fun Op_free as ^ {withOperation* `Operation'} -> `()' checkError*- #}
{# fun unsafe Wtime as ^ {} -> `Double' realToFrac #}
{# fun unsafe Wtick as ^ {} -> `Double' realToFrac #}

-- | Return the process group from a communicator.
{# fun unsafe Comm_group as ^
               {fromComm `Comm', alloca- `Group' peekGroup*} -> `()' checkError*- #}


{# fun Irecv as ^
           { id `BufferPtr', id `Count', fromDatatype `Datatype', fromRank `Rank', fromTag `Tag', fromComm `Comm', alloca- `Request' peekRequest*} -> `()' checkError*- #}

-- | Like 'isend', but stores @Request@ at the supplied pointer. Useful
-- for making arrays of @Requests@ that could be passed to 'waitall'
{# fun unsafe Isend as isendPtr
           { id `BufferPtr', id `Count', fromDatatype `Datatype', fromRank `Rank', fromTag `Tag', fromComm `Comm', castPtr `Ptr Request'} -> `()' checkError*- #}

-- | Like 'ibsend', but stores @Request@ at the supplied pointer. Useful
-- for making arrays of @Requests@ that could be passed to 'waitall'
{# fun unsafe Ibsend as ibsendPtr
           { id `BufferPtr', id `Count', fromDatatype `Datatype', fromRank `Rank', fromTag `Tag', fromComm `Comm', castPtr `Ptr Request'} -> `()' checkError*- #}

-- | Like 'issend', but stores @Request@ at the supplied pointer. Useful
-- for making arrays of @Requests@ that could be passed to 'waitall'
{# fun unsafe Issend as issendPtr
           { id `BufferPtr', id `Count', fromDatatype `Datatype', fromRank `Rank', fromTag `Tag', fromComm `Comm', castPtr `Ptr Request'} -> `()' checkError*- #}

-- | Like 'irecv', but stores @Request@ at the supplied pointer. Useful
-- for making arrays of @Requests@ that could be passed to 'waitall'
{# fun Irecv as irecvPtr
           { id `BufferPtr', id `Count', fromDatatype `Datatype', fromRank `Rank', fromTag `Tag', fromComm `Comm', castPtr `Ptr Request'} -> `()' checkError*- #}

