Sto cercando di trovare un modo per tradurre la notazione ricorsiva normale come come | fib | funzione sotto a una freccia, conservando la maggior parte della struttura della notazione ricorsiva possibile. Inoltre vorrei come ispezionare la freccia. Per questo ho creato un tipo di dati che contiene un costruttore per ogni freccia {..} classe:Ricorsione (o associazione) osservabile in Frecce
Fib:
fib 0 = 0
fib 1 = 1
fib n = fib (n-2) + fib (n-1)
mio R tipo di dati, le istanze di questo tipo di dati consistono nella mappatura al costruttore appropriato :
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
Traducendo l'| fib | la funzione dall'alto ha avuto come risultato la seguente definizione . Non è tuttavia consentito a causa del proc n on RHS della dichiarazione per | fibz |. So che la grammatica della notazione delle frecce impedisce questo, ma qual è il motivo sottostante per questo ?
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
Riscrivere la funzione di cui sopra per utilizzare una dichiarazione di let compila. Tuttavia, qui sorge il mio secondo problema. Voglio essere in grado di ispezionare la ricorsione dove accade. Tuttavia, in questo caso | fibz | è un albero infinito . Vorrei catturare la ricorsione in fibz, I speravo che il rec mi aiutasse con quello in combinazione con | loop | ma forse mi sbaglio?
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
Fondamentalmente, è possibile osservare questo tipo di ricorsione? (Forse anche entro i confini di Notazione Arrow) Potrei forse aggiungere un altro costruttore come fix. Forse dovrei essere in grado di osservare il legame delle variabili in modo che il riferimento a loro sia possibile. Tuttavia, ciò non rientrerebbe nello scopo di Arrows.
Qualche idea su questo?
Aggiornamento 1: Mi viene in mente questo modulo, al di fuori della notazione a freccia. Ciò nasconde la ricorsione all'interno dello app
e quindi finisco con una rappresentazione finita della freccia. Tuttavia, voglio ancora essere in grado di, ad es. sostituire la chiamata a fib
all'interno di app
in una versione ottimizzata di 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)))))))
Questo codice corrisponde con quanto segue in freccia notazione:
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)
Come scriveresti 'fib' in termini di' R'? –
@SjoerdVisscher Ho aggiornato la domanda per includere 'fib' in termini di' R'. (ma usando i metodi di classe) –
C'è una discussione concorrente in corso su [reddit] (http://www.reddit.com/r/haskell/comments/11ayds/observable_recursion_in_arrows/). –