{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Language.Expression.Choice where
import Data.Data
import Data.Union
import Control.Lens hiding (op)
import Language.Expression
data OpChoice ops (t :: * -> *) a where
OpThis :: op t a -> OpChoice (op : ops) t a
OpThat :: OpChoice ops t a -> OpChoice (op : ops) t a
deriving (Typeable)
_OpThis :: Prism' (OpChoice (op : ops) t a) (op t a)
_OpThis = prism' OpThis $ \case
OpThis x -> Just x
OpThat _ -> Nothing
_OpThat :: Prism' (OpChoice (op : ops) t a) (OpChoice ops t a)
_OpThat = prism' OpThat $ \case
OpThis _ -> Nothing
OpThat x -> Just x
noOps :: OpChoice '[] t a -> x
noOps = \case
instance HFunctor (OpChoice '[]) where
hmap _ = noOps
instance HTraversable (OpChoice '[]) where
htraverse _ = noOps
instance HFoldableAt k (OpChoice '[]) where
hfoldMap _ = noOps
instance (HFunctor op, HFunctor (OpChoice ops)) =>
HFunctor (OpChoice (op : ops)) where
hmap f = \case
OpThis x -> OpThis (hmap f x)
OpThat x -> OpThat (hmap f x)
instance (HTraversable op, HTraversable (OpChoice ops)) =>
HTraversable (OpChoice (op : ops)) where
htraverse f = \case
OpThis x -> OpThis <$> htraverse f x
OpThat x -> OpThat <$> htraverse f x
instance (HFoldableAt k op, HFoldableAt k (OpChoice ops)) =>
HFoldableAt k (OpChoice (op : ops)) where
hfoldMap f = \case
OpThis x -> hfoldMap f x
OpThat x -> hfoldMap f x
newtype AsOp (t :: * -> *) a op = AsOp (op t a)
makeWrapped ''AsOp
choiceToUnion :: OpChoice ops t a -> Union (AsOp t a) ops
choiceToUnion = \case
OpThis x -> This (AsOp x)
OpThat x -> That (choiceToUnion x)
unionToChoice :: Union (AsOp t a) ops -> OpChoice ops t a
unionToChoice = \case
This (AsOp x) -> OpThis x
That x -> OpThat (unionToChoice x)
_OpChoice
:: Iso (OpChoice ops t a) (OpChoice ops' t' a')
(Union (AsOp t a) ops) (Union (AsOp t' a') ops')
_OpChoice = iso choiceToUnion unionToChoice
class ChooseOp op ops where
chooseOp :: Prism' (OpChoice ops t a) (op t a)
instance UElem op ops i => ChooseOp op ops where
chooseOp = _OpChoice . uprism . _Wrapped
class SubsetOp ops1 ops2 where
subsetOp :: Prism' (OpChoice ops2 t a) (OpChoice ops1 t a)
instance USubset ops1 ops2 is => SubsetOp ops1 ops2 where
subsetOp = _OpChoice . usubset . from _OpChoice
newtype HFree' ops v a = HFree' { getHFree' :: HFree (OpChoice ops) v a }
deriving (Typeable)
deriving instance
(Data (HFree (OpChoice ops) v a), Typeable (HFree' ops v a)) =>
Data (HFree' ops v a)
instance (HFunctor (OpChoice ops)) => HFunctor (HFree' ops) where
hmap f = HFree' . hmap f . getHFree'
instance (HTraversable (OpChoice ops)) => HTraversable (HFree' ops) where
htraverse f = fmap HFree' . htraverse f . getHFree'
instance HPointed (HFree' ops) where
hpure = HFree' . hpure
instance (HFunctor (OpChoice ops)) => HBind (HFree' ops) where
x ^>>= f = (HFree' . (^>>= (getHFree' . f)) . getHFree') x
instance (HFunctor (OpChoice ops)) => HMonad (HFree' ops) where
instance (HFoldableAt k (OpChoice ops), HFunctor (OpChoice ops)) =>
HFoldableAt k (HFree' ops) where
hfoldMap f (HFree' x) = hfoldMap f x
squashExpression
:: (HFunctor op1,
HFunctor op2,
HFunctor (OpChoice ops),
ChooseOp op1 ops,
ChooseOp op2 ops)
=> HFree op1 (HFree op2 v) a -> HFree' ops v a
squashExpression
= HFree'
. hjoin
. hmap (hduomapFirst' (review chooseOp))
. hduomapFirst' (review chooseOp)
hwrap'
:: (HFunctor op, HFunctor (OpChoice ops), ChooseOp op ops)
=> op (HFree' ops v) a -> HFree' ops v a
hwrap' = HFree' . HWrap . review chooseOp . hmap getHFree'
makeWrapped ''HFree'