{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE EmptyCase #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} module Data.Vessel.Single where import Data.These import Data.Patch (Group(..), Additive) import Data.Semigroup import Data.Functor.Identity import Data.Witherable import Data.Functor.Compose import Data.Functor.Const import Data.Align import Data.Aeson import GHC.Generics (Generic) import Data.Vessel.Class import Data.Vessel.Selectable import Data.Vessel.ViewMorphism ------- Simple structure components ------- -- | A functor-indexed container for a single deletable item. newtype SingleV (a :: *) (g :: * -> *) = SingleV { unSingleV :: g (First (Maybe a)) } deriving (Generic) deriving instance (Eq (g (First (Maybe a)))) => Eq (SingleV a g) deriving instance (Ord (g (First (Maybe a)))) => Ord (SingleV a g) deriving instance (Show (g (First (Maybe a)))) => Show (SingleV a g) deriving instance (Read (g (First (Maybe a)))) => Read (SingleV a g) instance (Semigroup (g (First (Maybe a)))) => Semigroup (SingleV a g) where (SingleV x) <> (SingleV y) = SingleV (x <> y) instance (Monoid (g (First (Maybe a)))) => Monoid (SingleV a g) where mempty = SingleV mempty mappend (SingleV x) (SingleV y) = SingleV (mappend x y) instance (Group (g (First (Maybe a)))) => Group (SingleV a g) where negateG (SingleV x) = SingleV (negateG x) instance (Additive (g (First (Maybe a)))) => Additive (SingleV a g) instance View (SingleV a) where cropV f (SingleV s) (SingleV i) = Just $ SingleV $ f s i nullV (SingleV _) = False condenseV :: (Foldable t, Filterable t, Functor t) => t (SingleV a g) -> SingleV a (Compose t g) condenseV m = SingleV . Compose $ fmap unSingleV m disperseV :: (Align t) => SingleV a (Compose t g) -> t (SingleV a g) disperseV (SingleV (Compose x)) = fmap SingleV x mapV :: (forall x. f x -> g x) -> SingleV a f -> SingleV a g mapV f (SingleV x) = SingleV $ f x traverseV :: (Applicative m) => (forall x. f x -> m (g x)) -> SingleV a f -> m (SingleV a g) traverseV f (SingleV x) = SingleV <$> f x mapMaybeV f (SingleV x) = SingleV <$> f x alignWithMaybeV f (SingleV x) (SingleV y) = SingleV <$> f (These x y) alignWithV f (SingleV x) (SingleV y) = SingleV $ f $ These x y deriving instance ToJSON (g (First (Maybe a))) => ToJSON (SingleV a g) deriving instance FromJSON (g (First (Maybe a))) => FromJSON (SingleV a g) instance Selectable (SingleV a) () where type Selection (SingleV a) () = Maybe a selector p () = SingleV p selection () (SingleV x) = getFirst . runIdentity $ x lookupSingleV :: SingleV a Identity -> Maybe a lookupSingleV = getFirst . runIdentity . unSingleV type instance ViewQueryResult (SingleV a (Const g)) = SingleV a Identity -- Note. the result functions always return Just; a "Single" is always -- present in the result, only that the value it may be is possibly a Nothing. singleV :: (Applicative m, Applicative n) => ViewMorphism m n (Const g (Maybe a)) (SingleV a (Const g)) singleV = ViewMorphism toSingleV fromSingleV toSingleV :: (Applicative m, Applicative n) => ViewHalfMorphism m n (Const g (Maybe a)) (SingleV a (Const g)) toSingleV = ViewHalfMorphism { _viewMorphism_mapQuery = \(Const x) -> pure . SingleV $ Const x , _viewMorphism_mapQueryResult = \(SingleV (Identity (First x))) -> pure (Identity x) } fromSingleV :: (Applicative m, Applicative n) => ViewHalfMorphism m n (SingleV a (Const g)) (Const g (Maybe a)) fromSingleV = ViewHalfMorphism { _viewMorphism_mapQuery = \(SingleV (Const g)) -> pure $ Const g , _viewMorphism_mapQueryResult = pure . SingleV . fmap First } -- | A gadget to "traverse" over a SingleV handleSingleVSelector :: forall a f g m. Functor m => (forall x. x -> f x -> g x) -> m (First (Maybe a)) -> SingleV a f -> m (SingleV a g) handleSingleVSelector k f (SingleV xs) = (\y -> SingleV $ k y xs) <$> f -- | Non-existentialized mapV; since the contained value is known mapSingleV :: (f (First (Maybe a)) -> g (First (Maybe a))) -> SingleV a f -> SingleV a g mapSingleV f (SingleV xs) = SingleV (f xs)