{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Data.Text1(
Text1(Text1)
, length1
, compareLength1
, _head1
, _tail1
, _last1
, _init1
, AsText1(_Text1)
, IsText1(packed1, tpacked1, unpacked1, tunpacked1, text1)
, isText1
, AsSingle(_Single)
, OneAnd(_OneAnd)
) where
import Control.Applicative(Applicative)
import Control.Category(Category(id, (.)))
import Control.Lens(Iso, IndexedTraversal', Optic', Profunctor, Choice, Reversing(reversing), Cons(_Cons), Snoc(_Snoc), uncons, unsnoc, Iso', Lens', Prism', prism', iso, lens, (^.), (#), (^?), (%~), _1, _2, from, indexing, traversed)
import Control.Monad(Monad(return, (>>=), (>>)))
import Data.Binary(Binary(put, get))
import Data.Char(Char)
import Data.Data(Data)
import Data.Eq(Eq)
import Data.Foldable(toList)
import Data.Functor(Functor(fmap))
import Data.Int(Int)
import Data.List as List(null)
import Data.List.NonEmpty(NonEmpty((:|)))
import Data.Maybe(Maybe(Just, Nothing))
import Data.Ord(Ord, Ordering)
import Data.Semigroup(Semigroup((<>)))
import Data.String(String)
import Data.Text(Text)
import qualified Data.Text as Text(cons, snoc, append, null, empty, length, compareLength, uncons, pack, unpack, singleton)
import Data.Text.Lens(IsText(packed, builder))
import Data.Traversable(Traversable(traverse))
import Data.Tuple(uncurry)
import Data.Typeable(Typeable)
import Prelude(Show(show), Num((+), (-)))
data Text1 =
Text1
Char
Text
deriving (Eq, Ord, Data, Typeable)
instance Show Text1 where
show (Text1 h t) =
show (Text.cons h t)
instance Semigroup Text1 where
Text1 h1 t1 <> t =
Text1 h1 (Text.append t1 (_Text1 # t))
instance Binary Text1 where
put (Text1 h t) =
put h >> put t
get =
do h <- get
t <- get
return (Text1 h t)
length1 ::
Text1
-> Int
length1 (Text1 _ t) =
1 + Text.length t
compareLength1 ::
Text1
-> Int
-> Ordering
compareLength1 (Text1 _ t) n =
Text.compareLength t (n - 1)
_head1 ::
Lens'
Text1
Char
_head1 =
lens
(\(Text1 h _) -> h)
(\(Text1 _ t) h -> Text1 h t)
_tail1 ::
Lens'
Text1
Text
_tail1 =
lens
(\(Text1 _ t) -> t)
(\(Text1 h _) t -> Text1 h t)
_last1 ::
Lens'
Text1
Char
_last1 =
lens
(\(Text1 h t) -> case unsnoc t of
Nothing -> h
Just (_, l) -> l)
(\(Text1 h t) x -> case unsnoc t of
Nothing -> Text1 x t
Just (i, _) -> Text1 h (Text.snoc i x))
_init1 ::
Lens'
Text1
Text
_init1 =
lens
(\(Text1 h t) -> case unsnoc t of
Nothing -> Text.empty
Just (i, _) -> Text.cons h i)
(\(Text1 h t) x ->
let r = case unsnoc t of
Nothing -> h
Just (_, l) -> l
in case uncons x of
Nothing -> Text1 r Text.empty
Just (h', t') -> Text1 h' (Text.snoc t' r))
class AsText1 p f s where
_Text1 ::
Optic' p f s Text1
instance AsText1 p f Text1 where
_Text1 =
id
instance (Profunctor p, Functor f) => AsText1 p f (NonEmpty Char) where
_Text1 =
packed1
instance (Choice p, Applicative f) => AsText1 p f String where
_Text1 =
prism'
(\(Text1 h t) -> h : Text.unpack t)
(fmap (\(h, t) -> Text1 h (Text.pack t)) . uncons)
instance (Choice p, Applicative f) => AsText1 p f Text where
_Text1 =
prism'
(\(Text1 h t) -> Text.cons h t)
(fmap (uncurry Text1) . Text.uncons)
class IsText1 t where
packed1 ::
Iso'
(NonEmpty Char)
t
tpacked1 ::
Iso'
Text
(Maybe t)
tpacked1 =
iso
(fmap (\(h, t') -> (h :| Text.unpack t') ^. packed1) . Text.uncons)
(\t -> case t of
Nothing -> Text.empty
Just t' -> Text.pack (toList (packed1 # t')))
unpacked1 ::
Iso'
t
(NonEmpty Char)
unpacked1 =
from packed1
tunpacked1 ::
Iso'
(Maybe t)
Text
tunpacked1 =
from tpacked1
text1 ::
IndexedTraversal' Int t Char
text1 =
unpacked1 . traversed
instance IsText1 Text1 where
packed1 =
iso
(\(h :| t) -> Text1 h (t ^. packed))
(\(Text1 h t) -> h :| (packed # t))
tpacked1 =
iso
(fmap (\(h, t') -> Text1 h t') . Text.uncons)
(\t -> case t of
Nothing -> Text.empty
Just (Text1 h t') -> Text.cons h t')
instance IsText1 (NonEmpty Char) where
packed1 =
id
text1 =
indexing traverse
instance IsText (Maybe Text1) where
packed =
packed . isText1
builder =
from isText1 . builder
instance Reversing Text1 where
reversing (Text1 h t) =
case uncons (reversing t) of
Nothing -> Text1 h Text.empty
Just (h', t') -> Text1 h' (Text.snoc t' h)
isText1 ::
Iso' Text (Maybe Text1)
isText1 =
iso
(\x ->
fmap (\(h, t) -> Text1 h t) (Text.uncons x))
(\x -> case x of
Nothing ->
Text.empty
Just (Text1 h t) ->
Text.cons h t)
instance Cons (Maybe Text1) (Maybe Text1) Char Char where
_Cons =
prism'
(\(h, t) -> (_Cons # (h, isText1 # t)) ^. isText1)
(\t -> fmap (_2 %~ (^. isText1)) ((isText1 # t) ^? _Cons))
instance Snoc (Maybe Text1) (Maybe Text1) Char Char where
_Snoc =
prism'
(\(t, s) -> (_Snoc # (isText1 # t, s)) ^. isText1)
(\t -> fmap (_1 %~ (^. isText1)) ((isText1 # t) ^? _Snoc))
class AsSingle c a | c -> a where
_Single :: Prism' c a
instance AsSingle [a] a where
_Single =
prism'
(\a -> [a])
(\c -> case c of
[a] -> Just a
_ -> Nothing)
instance AsSingle Text Char where
_Single =
prism'
Text.singleton
(\t -> uncons t >>= \(h, t') -> if Text.null t' then Just h else Nothing)
instance AsSingle (Maybe a) a where
_Single =
prism'
Just
id
instance AsSingle (NonEmpty a) a where
_Single =
prism'
(\a -> a :| [])
(\(h :| t) -> if List.null t then Just h else Nothing)
instance AsSingle Text1 Char where
_Single =
prism'
(\c -> Text1 c Text.empty)
(\(Text1 h t) -> if Text.null t then Just h else Nothing)
class OneAnd s t a b x y | s -> a, s -> x, t -> b, t -> y, s b -> t, x b -> t, t a -> s, y a -> s where
_OneAnd ::
Iso s t (a, x) (b, y)
instance OneAnd Text1 Text1 Char Char Text Text where
_OneAnd =
iso
(\(Text1 h t) -> (h, t))
(uncurry Text1)
instance OneAnd (NonEmpty a) (NonEmpty b) a b [a] [b] where
_OneAnd =
iso
(\(h :| t) -> (h, t))
(uncurry (:|))