{-# LANGUAGE GeneralizedNewtypeDeriving #-} -- | Types to avoid source destination confusion while copying. module Raaz.Core.Types.Copying ( -- * Copying. -- $copyconvention$ Src(..), Dest(..), source, destination ) where import Foreign.Storable ( Storable ) -- $copyconvention$ -- -- Consider a copy operation that involves copying data between two -- entities of the same type. If the source and target is confused -- this can lead to bugs. The types `Src` and `Dest` helps in avoiding -- this confusion. The convention that we follow is that copy function -- mark its destination and source explicitly at the type level. The -- actual constructors for the type `Src` and `Dest` are not available -- to users of the library. Instead they use the smart constructors -- `source` and `destination` when passing arguments to these -- functions. -- -- The developers of the raaz library do have access to the -- constructors. However, it is unlikely one would need it. Since both -- `Src` and `Dest` derive the underlying `Storable` instance, one can -- mark `Src` and `Dest` in calls to `FFI` functions as well. -- | The source of a copy operation. newtype Src a = Src { unSrc :: a } deriving Storable -- | smart constructor for source source :: a -> Src a source = Src instance Functor Src where fmap f = Src . f . unSrc -- | The destination of a copy operation. -- -- Note to Developers of Raaz: Since the `Dest` type inherits the -- Storable instance of the base type, one can use this type in -- foreign functions. newtype Dest a = Dest { unDest :: a } deriving Storable -- | smart constructor for destionation. destination :: a -> Dest a destination = Dest instance Functor Dest where fmap f = Dest . f . unDest