-- | A 'Letter' with unknown annotation. We sometimes want to encode that we
-- are dealing with @Letter@s in an alphabet, but we do not want to commit to a
-- certain alphabet (just yet).
--
-- This module allows us to make explicit that we do not know the specific
-- alphabet type yet.
--
-- One should NEVER blindly coerce, since the order and limits of @Letter@'s
-- might well be different.

module Biobase.Primary.Unknown where

import           Data.Aeson
import           Control.Applicative ((<$>))
import           Control.Arrow ((***),first)
import           Data.Hashable
import           Data.Ix (Ix(..))
import           Data.Map.Strict (Map)
import           Data.Primitive.Types
import           Data.Tuple (swap)
import           Data.Vector.Unboxed.Deriving
import           Debug.Trace
import           GHC.Base (remInt,quotInt)
import           GHC.Generics (Generic)
import           GHC.Read
import qualified Data.Bijection.Map as B
import qualified Data.ByteString.Char8 as BS
import qualified Data.ByteString.Lazy.Char8 as BSL
import qualified Data.Map.Strict as M
import qualified Data.Text as T
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Generic.Mutable as VGM
import qualified Data.Vector.Unboxed as VU
import qualified Text.ParserCombinators.ReadPrec as RP
import qualified Text.Read.Lex as Lex

import           Biobase.Primary.Letter



-- | @Unknown@ phantom type.

data Unknown



-- | Creating an unknown letter.

unk  Int  Letter Unknown n
unk :: Int -> Letter Unknown n
unk = Int -> Letter Unknown n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter



-- *** instances

instance Show (Letter Unknown n) where
  show :: Letter Unknown n -> String
show (Letter Int
i) = String
"U " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
i

instance Read (Letter Unknown n) where
  readPrec :: ReadPrec (Letter Unknown n)
readPrec = ReadPrec (Letter Unknown n) -> ReadPrec (Letter Unknown n)
forall a. ReadPrec a -> ReadPrec a
parens (ReadPrec (Letter Unknown n) -> ReadPrec (Letter Unknown n))
-> ReadPrec (Letter Unknown n) -> ReadPrec (Letter Unknown n)
forall a b. (a -> b) -> a -> b
$ do
    Lex.Ident String
u <- ReadPrec Lexeme
lexP
    case String
u of
      String
"U"  Int -> Letter Unknown n
forall k (n :: k). Int -> Letter Unknown n
unk (Int -> Letter Unknown n)
-> ReadPrec Int -> ReadPrec (Letter Unknown n)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadPrec Int
forall a. Read a => ReadPrec a
readPrec
      String
_    ReadPrec (Letter Unknown n)
forall a. ReadPrec a
RP.pfail

instance Enum (Letter Unknown n) where
    succ :: Letter Unknown n -> Letter Unknown n
succ (Letter Int
x) = Int -> Letter Unknown n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter (Int -> Letter Unknown n) -> Int -> Letter Unknown n
forall a b. (a -> b) -> a -> b
$ Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
    pred :: Letter Unknown n -> Letter Unknown n
pred (Letter Int
x) = Int -> Letter Unknown n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter (Int -> Letter Unknown n) -> Int -> Letter Unknown n
forall a b. (a -> b) -> a -> b
$ Int
xInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1
    toEnum :: Int -> Letter Unknown n
toEnum = Int -> Letter Unknown n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter
    fromEnum :: Letter Unknown n -> Int
fromEnum = Letter Unknown n -> Int
forall seqTy k (nameTy :: k). Letter seqTy nameTy -> Int
getLetter

instance MkPrimary (VU.Vector Int) Unknown n where
  primary :: Vector Int -> Primary Unknown n
primary = (Int -> Letter Unknown n) -> Vector Int -> Primary Unknown n
forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
VU.map Int -> Letter Unknown n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter
  {-# Inline primary #-}

instance ToJSON (Letter Unknown n) where
  toJSON :: Letter Unknown n -> Value
toJSON = Int -> Value
forall a. ToJSON a => a -> Value
toJSON (Int -> Value)
-> (Letter Unknown n -> Int) -> Letter Unknown n -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Letter Unknown n -> Int
forall seqTy k (nameTy :: k). Letter seqTy nameTy -> Int
getLetter

instance FromJSON (Letter Unknown n) where
  parseJSON :: Value -> Parser (Letter Unknown n)
parseJSON = (Int -> Letter Unknown n)
-> Parser Int -> Parser (Letter Unknown n)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int -> Letter Unknown n
forall k seqTy (nameTy :: k). Int -> Letter seqTy nameTy
Letter (Parser Int -> Parser (Letter Unknown n))
-> (Value -> Parser Int) -> Value -> Parser (Letter Unknown n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Parser Int
forall a. FromJSON a => Value -> Parser a
parseJSON