{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilyDependencies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ViewPatterns #-} ----------------------------------------------------------------------------- -- | -- Module : Numeric.Tuple.Lazy -- Copyright : (c) Artem Chirkin -- License : BSD3 -- -- ----------------------------------------------------------------------------- module Numeric.Tuple.Lazy ( Id (..), Tuple , TypedList (U, (:*), (:$), (:!), Empty, TypeList, Cons, Snoc, Reverse) , (*$), ($*), (*!), (!*) ) where import Control.Arrow (first) import Control.Monad.Fix import Control.Monad.Zip import Data.Bits (Bits, FiniteBits) import Data.Coerce import Data.Data (Data) import Data.Foldable import Data.Functor.Classes import Data.Ix (Ix) import Data.Monoid as Mon (Monoid (..)) import Data.Semigroup as Sem (Semigroup (..)) import Data.String (IsString) import Foreign.Storable (Storable) import GHC.Base (Type, Any) import GHC.Generics (Generic, Generic1) import qualified Text.Read as P import Unsafe.Coerce (unsafeCoerce) import Data.Type.List import Numeric.TypedList -- | This is an almost complete copy of `Data.Functor.Identity` -- by (c) Andy Gill 2001. newtype Id a = Id { runId :: a } deriving ( Bits, Bounded, Data, Enum, Eq, FiniteBits, Floating, Fractional , Generic, Generic1, Integral, IsString, Ix, Monoid, Num, Ord , Real, RealFrac, RealFloat, Semigroup, Storable, Traversable) instance Read a => Read (Id a) where readsPrec d = fmap (first Id) . readsPrec d instance Show a => Show (Id a) where showsPrec d = showsPrec d . runId instance Read1 Id where liftReadPrec r _ = coerce r liftReadListPrec = liftReadListPrecDefault liftReadList = liftReadListDefault instance Show1 Id where liftShowsPrec f _ = coerce f instance Eq1 Id where liftEq = coerce instance Ord1 Id where liftCompare = coerce instance Foldable Id where foldMap = coerce elem = k (==) where k :: (a -> a -> Bool) -> a -> Id a -> Bool k = coerce foldl = coerce foldl' = coerce foldl1 _ = coerce foldr f z (Id x) = f x z foldr' = foldr foldr1 _ = coerce length _ = 1 maximum = coerce minimum = coerce null _ = False product = coerce sum = coerce toList (Id x) = [x] instance Functor Id where fmap = coerce instance Applicative Id where pure = Id (<*>) = coerce instance Monad Id where m >>= k = k (runId m) instance MonadFix Id where mfix f = Id (fix (runId . f)) instance MonadZip Id where mzipWith = coerce munzip = coerce -- | A tuple indexed by a list of types type Tuple = (TypedList Id :: [Type] -> Type) {-# COMPLETE U, (:$) #-} {-# COMPLETE U, (:!) #-} {-# COMPLETE Empty, (:$) #-} {-# COMPLETE Empty, (:!) #-} -- | Constructing a type-indexed list pattern (:$) :: forall (xs :: [Type]) . () => forall (y :: Type) (ys :: [Type]) . (xs ~ (y ': ys)) => y -> Tuple ys -> Tuple xs pattern (:$) x xs <- (Id x :* xs) where (:$) = (*$) infixr 5 :$ -- | Constructing a type-indexed list pattern (:!) :: forall (xs :: [Type]) . () => forall (y :: Type) (ys :: [Type]) . (xs ~ (y ': ys)) => y -> Tuple ys -> Tuple xs pattern (:!) x xs <- (forceCons -> Id x :* xs) where (:!) = (*!) infixr 5 :! -- | Grow a tuple on the left O(1). (*$) :: x -> Tuple xs -> Tuple (x :+ xs) (*$) x xs = unsafeCoerce (unsafeCoerce x : unsafeCoerce xs :: [Any]) {-# INLINE (*$) #-} infixr 5 *$ -- | Grow a tuple on the left while evaluating arguments to WHNF O(1). (*!) :: x -> Tuple xs -> Tuple (x :+ xs) (*!) !x !xs = let !r = unsafeCoerce x : unsafeCoerce xs :: [Any] in unsafeCoerce r {-# INLINE (*!) #-} infixr 5 *! -- | Grow a tuple on the right. -- Note, it traverses an element list inside O(n). ($*) :: Tuple xs -> x -> Tuple (xs +: x) ($*) xs x = unsafeCoerce (unsafeCoerce xs ++ [unsafeCoerce x] :: [Any]) {-# INLINE ($*) #-} infixl 5 $* -- | Grow a tuple on the right while evaluating arguments to WHNF. -- Note, it traverses an element list inside O(n). (!*) :: Tuple xs -> x -> Tuple (xs +: x) (!*) !xs !x = let !r = go (unsafeCoerce x) (unsafeCoerce xs) :: [Any] go :: Any -> [Any] -> [Any] go z [] = z `seq` [z] go z (y : ys) = y `seq` y : go z ys in unsafeCoerce r {-# INLINE (!*) #-} infixl 5 !* instance All Semigroup xs => Sem.Semigroup (Tuple xs) where U <> U = U (x :$ xs) <> (y :$ ys) = (x <> y) *$ ( xs <> ys) instance ( RepresentableList xs , All Semigroup xs , All Monoid xs) => Mon.Monoid (Tuple xs) where mempty = go (tList @xs) where go :: forall (ys :: [Type]) . All Monoid ys => TypeList ys -> Tuple ys go U = U go (_ :* xs) = mempty *$ go xs #if !(MIN_VERSION_base(4,11,0)) mappend = (<>) #endif instance (RepresentableList xs, All Bounded xs) => Bounded (Tuple xs) where minBound = go (tList @xs) where go :: forall (ys :: [Type]) . All Bounded ys => TypeList ys -> Tuple ys go U = U go (_ :* xs) = minBound *$ go xs maxBound = go (tList @xs) where go :: forall (ys :: [Type]) . All Bounded ys => TypeList ys -> Tuple ys go U = U go (_ :* xs) = maxBound *$ go xs instance All Eq xs => Eq (Tuple xs) where (==) U U = True (==) (x :* tx) (y :* ty) = eq1 x y && tx == ty (/=) U U = False (/=) (x :* tx) (y :* ty) = not (eq1 x y) || tx /= ty -- | Lexicorgaphic ordering; same as normal Haskell lists. instance (All Eq xs, All Ord xs) => Ord (Tuple xs) where compare U U = EQ compare (x :* tx) (y :* ty) = compare1 x y <> compare tx ty instance All Show xs => Show (Tuple xs) where showsPrec = typedListShowsPrecC @Show ":$" showsPrec1 instance (All Read xs, RepresentableList xs) => Read (Tuple xs) where readPrec = typedListReadPrec @Read ":$" readPrec1 (tList @xs) readList = P.readListDefault readListPrec = P.readListPrecDefault -------------------------------------------------------------------------------- -- internal -------------------------------------------------------------------------------- forceCons :: Tuple xs -> Tuple xs forceCons U = U forceCons (Id x :* xs) = x `seq` xs `seq` (Id x :* xs)