    {-| Utilities for manipulating nucleotide sequences and locations on
    nucleotide sequences that occur on a forward or a reverse-complement
    strand.

    -}

    module Bio.Location.Strand ( Strand(..)
                               , Stranded(..), stranded
                               )
        where

    import qualified Data.ByteString.Lazy.Char8 as LBS
    import Data.Ix (Ix)

    import Bio.Sequence.SeqData

    -- | Sequence strand
    data Strand = Fwd | RevCompl deriving (Eq, Ord, Show, Read, Bounded, Enum, Ix)

    -- | A nucleotide sequence or location on a nucleotide sequence that
    --   lies on a specific strand and has an orientation.
    class Stranded s where
        revCompl :: s -> s

    -- | Convert the orientation of a 'Stranded' thing based on a
    --   specified 'Strand'
    stranded :: (Stranded s) => Strand -> s -> s
    stranded Fwd      = id
    stranded RevCompl = revCompl

    instance Stranded Strand where
        revCompl Fwd      = RevCompl
        revCompl RevCompl = Fwd

    instance Stranded Char where
        revCompl = compl

    -- Avoid using -XTypeSynonymInstances
    instance Stranded LBS.ByteString where
        revCompl = LBS.reverse . LBS.map compl