| 1 | {-# LANGUAGE DeriveDataTypeable, ExistentialQuantification, Rank2Types, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, PatternGuards #-} |
|---|
| 2 | |
|---|
| 3 | module TcBug where |
|---|
| 4 | |
|---|
| 5 | import Control.Arrow |
|---|
| 6 | import Control.Monad.Trans |
|---|
| 7 | import Control.Monad.Reader |
|---|
| 8 | import Data.Typeable |
|---|
| 9 | import Data.Maybe |
|---|
| 10 | |
|---|
| 11 | class (Eq t, Typeable t) => Transformer t a | t -> a where |
|---|
| 12 | transform :: (LayoutClass l a) => t -> l a -> |
|---|
| 13 | (forall l'. (LayoutClass l' a) => l' a -> (l' a -> l a) -> b) -> b |
|---|
| 14 | |
|---|
| 15 | class HList c a where |
|---|
| 16 | find :: (Transformer t a) => c -> t -> Maybe Int |
|---|
| 17 | |
|---|
| 18 | class Typeable a => Message a |
|---|
| 19 | |
|---|
| 20 | data (LayoutClass l a) => EL l a = forall l'. (LayoutClass l' a) => EL (l' a) (l' a -> l a) |
|---|
| 21 | |
|---|
| 22 | unEL :: (LayoutClass l a) => EL l a -> (forall l'. (LayoutClass l' a) => l' a -> b) -> b |
|---|
| 23 | unEL (EL x _) k = k x |
|---|
| 24 | |
|---|
| 25 | transform' :: (Transformer t a, LayoutClass l a) => t -> EL l a -> EL l a |
|---|
| 26 | transform' t (EL l det) = transform t l (\l' det' -> EL l' (det . det')) |
|---|
| 27 | |
|---|
| 28 | data Toggle a = forall t. (Transformer t a) => Toggle t |
|---|
| 29 | deriving (Typeable) |
|---|
| 30 | |
|---|
| 31 | instance (Typeable a) => Message (Toggle a) |
|---|
| 32 | |
|---|
| 33 | data MultiToggle ts l a = MultiToggle{ |
|---|
| 34 | currLayout :: EL l a, |
|---|
| 35 | currIndex :: Maybe Int, |
|---|
| 36 | transformers :: ts |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | instance (Show ts, Show (l a), LayoutClass l a) => Show (MultiToggle ts l a) where |
|---|
| 40 | |
|---|
| 41 | class Show (layout a) => LayoutClass layout a where |
|---|
| 42 | handleMessage :: layout a -> SomeMessage -> IO (Maybe (layout a)) |
|---|
| 43 | handleMessage l = return . pureMessage l |
|---|
| 44 | |
|---|
| 45 | pureMessage :: layout a -> SomeMessage -> Maybe (layout a) |
|---|
| 46 | pureMessage _ _ = Nothing |
|---|
| 47 | |
|---|
| 48 | instance (Typeable a, Show ts, HList ts a, LayoutClass l a) => LayoutClass (MultiToggle ts l) a where |
|---|
| 49 | handleMessage mt m |
|---|
| 50 | | Just (Toggle t) <- fromMessage m |
|---|
| 51 | , i@(Just _) <- find (transformers mt) t |
|---|
| 52 | = case currLayout mt of |
|---|
| 53 | EL l det -> do |
|---|
| 54 | l' <- fromMaybe l `fmap` handleMessage l (SomeMessage ReleaseResources) |
|---|
| 55 | return . Just $ |
|---|
| 56 | mt { |
|---|
| 57 | currLayout = (if cur then id else transform' t) (EL (det l') id), |
|---|
| 58 | currIndex = if cur then Nothing else i |
|---|
| 59 | } |
|---|
| 60 | where cur = (i == currIndex mt) |
|---|
| 61 | | otherwise |
|---|
| 62 | = case currLayout mt of |
|---|
| 63 | EL l det -> fmap (fmap (\x -> mt { currLayout = EL x det })) $ |
|---|
| 64 | handleMessage l m |
|---|
| 65 | |
|---|
| 66 | data LayoutMessages = ReleaseResources |
|---|
| 67 | deriving (Typeable, Eq) |
|---|
| 68 | |
|---|
| 69 | instance Message LayoutMessages |
|---|
| 70 | |
|---|
| 71 | data SomeMessage = forall a. Message a => SomeMessage a |
|---|
| 72 | |
|---|
| 73 | fromMessage :: Message m => SomeMessage -> Maybe m |
|---|
| 74 | fromMessage (SomeMessage m) = cast m |
|---|