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.