Given this interface:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeFamilies #-}
module Tlf where
import Data.Dynamic (Dynamic, fromDyn, toDyn)
import Data.Kind (Type)
import Data.Proxy (Proxy (Proxy))
import Data.Typeable (Typeable)
data Q = Q1 | Q2
deriving (Show)
data R1 = R1 deriving (Show)
data R2 = R2 deriving (Show)
newtype TL (a :: [Type]) = TL { unTL :: Dynamic }
someFun :: Q -> TL '[R1, R2]
someFun Q1 = (TL . toDyn) R1
someFun Q2 = (TL . toDyn) R2
I want to write a function that runs someFunc and extracts back the return value. This works:
myQ :: (Typeable a) => Proxy a -> Q -> a
myQ _ q = (fromDyn . unTL . someFun) q (error "This shouldn't happen!")
> myQ (Proxy :: Proxy R1) Q1
R1
But the additional Proxy is redundant and it is not as safe as it could be
*Tlf> myQ (Proxy :: Proxy R2) Q1
*** Exception: This shouldn't happen!
The thing is that I know that Q1 will yield R1. So I wrote this:
type family FunRes (a :: Q) :: Type where
FunRes 'Q1 = R1
FunRes 'Q2 = R2
But now I am stuck on how to put the pieces together. I tried:
myQ' :: forall q. q -> FunRes q
myQ' q = (fromDyn . unTL . someFun) q (error "This shouldn't happen!")
But ghc says no:
• Expected kind ‘Q’, but ‘q’ has kind ‘*’
• In the first argument of ‘FunRes’, namely ‘q’
In the type signature: myQ' :: forall q. q -> FunRes q
I also tried a few other things, but I always stumble over the error given above.