tutorial online funciones empresa descargar constructora company haskell

haskell - online - Rebobinado de notación para mónadas indexadas.



haskell pdf (1)

IIUC, el analizador de GHC en realidad se ejecuta después del tipógrafo ( source ). Eso explica por qué la situación que observas es teóricamente posible. El tipógrafo probablemente tiene algunas reglas de tipificación especiales para la do-notation, y estas pueden ser inconsistentes con lo que haría el tipógrafo con el código desugarrado.

Por supuesto, es razonable esperar que sean coherentes, por lo que recomendaría presentar un error de GHC.

Estaba siguiendo el documento "Flechas de la fortuna escandalosa" de Conor McBride y he publicado mi implementación de su código here . Brevemente, define los siguientes tipos y clases:

type a :-> b = forall i . a i -> b i class IFunctor f where imap :: (a :-> b) -> (f a :-> f b) class (IFunctor m) => IMonad m where skip :: a :-> m a bind :: (a :-> m b) -> (m a :-> m b) data (a := i) j where V :: a -> (a := i) i

Luego define dos tipos de enlaces, el último de los cuales usa (:=) para restringir el índice inicial:

-- Conor McBride''s "demonic bind" (?>=) :: (IMonad m) => m a i -> (a :-> m b) -> m b i (?>=) = flip bind -- Conor McBride''s "angelic bind" (>>=) :: (IMonad m) => m (a := j) i -> (a -> m b j) -> m b i m >>= f = bind (/(V a) -> f a) m

El último enlace funciona perfectamente bien para return vincular la notación do para usar mónadas indexadas con la extensión RebindableSyntax , utilizando las siguientes definiciones correspondientes para return y fail :

return :: (IMonad m) => a -> m (a := i) i return = skip . V fail :: String -> m a i fail = error

... pero el problema es que no puedo hacer que funcione el enlace anterior (es decir, (?>=) ). Intenté en cambio definir (>>=) y return a ser:

(>>=) :: (IMonad m) => m a i -> (a :-> m b) -> m b i (>>=) = (?>=) return :: (IMonad m) => a :-> m a return = skip

Entonces creé un tipo de datos garantizado para habitar un índice específico:

data Unit a where Unit :: Unit ()

Pero cuando trato de volver a enlazar notación do usando las nuevas definiciones para (>>=) y return , no funciona, como se demuestra en el siguiente ejemplo:

-- Without do notation test1 = skip Unit >>= /Unit -> skip Unit -- With do notation test2 = do Unit <- skip Unit skip Unit

test1 tipo test1 , pero test2 no lo hacen, lo cual es extraño, ya que pensé que todo lo que RebindableSyntax hizo fue dejar la notación desugar test2 a test1 , así que si test1 tipo, entonces ¿por qué no test2 ? El error que recibo es:

Couldn''t match expected type `t0 -> t1'' with actual type `a0 :-> m0 b0'' Expected type: m0 a0 i0 -> (t0 -> t1) -> m Unit () Actual type: m0 a0 i0 -> (a0 :-> m0 b0) -> m0 b0 i0 In a stmt of a ''do'' block: Unit <- skip Unit In the expression: do { Unit <- skip Unit; skip Unit }

El error permanece incluso cuando uso la sintaxis explícita de forall lugar del operador de tipo :-> .

Ahora, sé que hay otro problema con el uso del "enlace demoníaco", que es que no se puede definir (>>) , pero todavía quería ver hasta dónde podía llegar. ¿Alguien puede explicar por qué no puedo hacer que GHC desugar el "vínculo demoníaco", incluso cuando normalmente se comprueba?