{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
module Data.Parameterized.Some
  ( Some(..)
  , viewSome
  , mapSome
  , traverseSome
  , traverseSome_
  ) where
import Data.Hashable
import Data.Parameterized.Classes
data Some (f:: k -> *) = forall x . Some (f x)
instance TestEquality f => Eq (Some f) where
  Some x == Some y = isJust (testEquality x y)
instance OrdF f => Ord (Some f) where
  compare (Some x) (Some y) = toOrdering (compareF x y)
instance HashableF f => Hashable (Some f) where
  hashWithSalt s (Some x) = hashWithSaltF s x
  hash (Some x) = hashF x
instance ShowF f => Show (Some f) where
  show (Some x) = showF x
viewSome :: (forall tp . f tp -> r) -> Some f -> r
viewSome f (Some x) = f x
mapSome :: (forall tp . f tp -> g tp) -> Some f -> Some g
mapSome f (Some x) = Some $! f x
{-# INLINE traverseSome #-}
traverseSome :: Functor m
             => (forall tp . f tp -> m (g tp))
             -> Some f
             -> m (Some g)
traverseSome f (Some x) = Some `fmap` f x
{-# INLINE traverseSome_ #-}
traverseSome_ :: Functor m => (forall tp . f tp -> m ()) -> Some f -> m ()
traverseSome_ f (Some x) = (\_ -> ()) `fmap` f x