Estoy tratando de encontrar una forma de traducir la notación recursiva normal como como | fib | función debajo de una flecha, conservando la mayor cantidad posible de la estructura de la notación recursiva. Además, me gustaría como para inspeccionar la flecha. Por esta creé un tipo de datos que contiene un constructor para cada Flecha clase {..}:Recursividad observable (o vinculante) en Flechas
Fib:
fib 0 = 0
fib 1 = 1
fib n = fib (n-2) + fib (n-1)
Mi R tipo de datos, las instancias de este tipo de datos consisten en el mapeo al constructor apropiado :
data R x y where
-- Category
Id :: R a a
Comp :: R b c -> R a b -> R a c
-- Arrow
Arr :: (a -> b) -> R a b
Split :: R b c -> R b' c' -> R (b,b') (c,c')
Cache :: (a -> a -> Bool) -> R a a
-- ArrowChoice
Choice :: R b c -> R b' c' -> R (Either b b') (Either c c')
-- ArrowLoop
Loop :: R (b, d) (c, d) -> R b c
-- ArrowApply
Apply :: R (R b c, b) c
Traduciendo el | fib | la función de arriba primero dio como resultado la siguiente definición . Sin embargo, no está permitido debido al proceso en el RHS de la declaración para | fibz |. Sé que la gramática de la notación de flecha impide esto, pero ¿cuál es la razón subyacente de esto?
fib' :: (ArrowChoice r, ArrowLoop r) => r Int Int
fib' = proc x -> do
rec fibz <- proc n -> case n of
0 -> returnA -< 0
1 -> returnA -< 1
n' -> do l <- fibz -< (n'-2)
r <- fibz -< (n'-1)
returnA -< (l+r)
fibz -<< x
Reescribiendo la función anterior para usar una compilación de enunciados let. Sin embargo, aquí surge mi segundo problema. Quiero poder inspeccionar la recursión donde ocurre. Sin embargo, en este caso | fibz | es un árbol infinito . Me gustaría capturar la recursión en fibz, I esperaba que el rec me ayudara con eso en combinación con | loop | pero tal vez estoy equivocado?
fib'' :: (ArrowChoice r, ArrowLoop r, ArrowApply r) => r Int Int
fib'' = proc x -> do
let fibz = proc n -> case n of
0 -> returnA -< 0
1 -> returnA -< 1
n' -> do l <- fibz -< (n'-2)
r <- fibz -< (n'-1)
returnA -< (l+r)
fibz -<< x
Básicamente, ¿es posible observar este tipo de recursividad? (Tal vez incluso dentro de los límites de la notación de flecha) podría agregar otro constructor como fix. Tal vez debería ser capaz de observar el enlace de variables para que sea posible hacer referencia a ellas. Sin embargo, esto quedaría fuera del alcance de Arrows.
¿Alguna idea de esto?
Actualización 1: Se me ocurre este formulario, fuera de la notación de flecha. Esto oculta la recursividad dentro del app
y, por lo tanto, termino con una representación finita de la flecha. Sin embargo, aún deseo poder, p. Ej. reemplace la llamada a fib
dentro de app
a una versión optimizada de fib
.
fib :: (ArrowChoice r, ArrowLoop r, ArrowApply r) => r Int Int
fib
= (arr
(\ n ->
case n of
0 -> Left()
1 -> Right (Left())
n' -> Right (Right n'))
>>>
(arr (\() -> 0) |||
(arr (\() -> 1) |||
(arr (\ n' -> (n', n')) >>>
(first (arr (\ n' -> app (fib, n' - 2))) >>>
arr (\ (l, n') -> (n', l)))
>>>
(first (arr (\ n' -> app (fib, n' - 1))) >>>
arr (\ (r, l) -> (l + r)))))))
Este código corresponde a lo siguiente en la flecha de la notación:
fib :: (ArrowChoice r, ArrowLoop r, ArrowApply r) => r Int Int
fib = proc n ->
case n of
0 -> returnA -< 0
1 -> returnA -< 1
n' ->
do l <- fib -<< (n'-2)
r <- fib -<< (n'-1)
returnA -< (l+r)
¿Cómo se escribiría 'fib' en términos de' R'? –
@SjoerdVisscher Actualicé la pregunta para incluir 'fib' en términos de' R'. (pero usando los métodos de clase) –
Hay una discusión simultánea en [reddit] (http://www.reddit.com/r/haskell/comments/11ayds/observable_recursion_in_arrows/). –