Como elaborar os detalhes de uma mônada livre indexada ao tipo

Eu tenho usado uma mônada grátis para construir uma DSL. Como parte do idioma, há uminput comando, o objetivo é refletir quais tipos são esperados pela primitiva de entrada no nível de tipo para segurança adicional.

Por exemplo, eu quero poder escrever o seguinte programa.

concat :: Action '[String, String] ()
concat = do
  (x :: String) <- input
  (y :: String) <- input 
  output $ x ++ " " ++ y

Juntamente com uma função de avaliação

eval :: Action params res -> HList params -> [String]
eval = ...

Que funciona da seguinte maneira ..

> eval concat ("a" `HCons` "b" `HCons` HNil)
["a b"]

Aqui está o que eu tenho até agora.

data HList i where
  HNil :: HList '[]
  HCons :: h -> HList t -> HList (h ': t)

type family Append (a :: [k]) (b :: [k]) :: [k] where
  Append ('[]) l = l
  Append (e ': l) l' = e ': (Append l l')

data ActionF next where
   Input :: (a -> next) ->  ActionF next
   Output :: String -> next -> ActionF next

instance Functor ActionF where
  fmap f (Input c) = Input (fmap f c)
  fmap f (Output s n) = Output s (f n)

data FreeIx f i a where
  Return :: a -> FreeIx f '[] a
  Free :: f (FreeIx f i a) -> FreeIx f i a

type Action i a = FreeIx ActionF i a

liftF :: Functor f => f a -> FreeIx f i a
liftF = Free . fmap Return

input :: forall a . Action '[a] a
input = liftF (Input id)

output :: String -> Action '[] ()
output s = liftF (Output s ())

bind :: Functor f => FreeIx f t a -> (a -> FreeIx f v b) -> FreeIx f (Append t v) b
bind (Return a) f = f a
bind (Free x) f   = Free (fmap (flip bind f) x)

O problema é queliftF não digita cheque.

liftF :: Functor f => Proxy i -> f a -> FreeIx f i a
liftF p = Free . fmap Return

Essa é a abordagem correta?

Eu pensei que alguma inspiração poderia vir domônada de efeito pacote. Foi isso que levou à definição deReturn eFree.

Para mais histórias de fundo: vi em vários lugares que os usuários definirão DSLs dessa maneira e depois definirão uma função de avaliaçãoeval :: Action a -> [String] -> a ou algo semelhante. O claro problema dessa abordagem é que todos os argumentos devem ter o mesmo tipo e não há garantia estática de que o número correto de argumentos será fornecido. Esta é uma tentativa de resolver este problema.

questionAnswers(6)

yourAnswerToTheQuestion