Sto leggendo la programmazione di John Hughes con le frecce. C'è un pezzo di codice che non riesco davvero a capire. Il codice è il seguente:Funzione di ritardo della freccia di Haskell
import Control.Arrow.Operations
import Control.Arrow
import Control.Category
import Prelude hiding ((.),id)
newtype SF a b = SF {runSF :: [a] -> [b]}
instance Category SF where
id = SF id
(.) (SF f) (SF g) = SF $ \x -> f (g x)
(.*.) :: (a -> b) -> (c -> d) -> (a,c) -> (b,d)
(.*.) f g (a,c) = (f a, g c)
instance Arrow SF where
arr f = SF (map f)
first (SF f) = SF (uncurry zip . (f .*. id) . unzip)
instance ArrowLoop SF where
loop (SF f) = SF $ \as -> let (bs,cs) = unzip (f (zip as (stream cs))) in bs
where stream ~(x:xs) = x:stream xs
instance ArrowChoice SF where
left (SF f) = SF (\xs -> combine xs (f [y | Left y <- xs]))
where combine (Left y: xs) (z:zs) = Left z : combine xs zs
combine (Right y :xs) zs = Right y : combine xs zs
combine [] zs = []
instance ArrowCircuit SF where
delay x = SF (x:)
e poi
mapA :: ArrowChoice arr => arr a b -> arr [a] [b]
listcase [] = Left()
listcase (x:xs) = Right (x,xs)
mapA f = arr listcase >>>
arr (const []) ||| (f *** mapA f >>> arr (uncurry (:)))
Quello che non riesco a capire è che
> runSF (mapA (delay 0)) [[1,2,3],[4,5],[6],[7,8],[9,10,11],[12,13,14,15]]
[[0,0,0],[1,2],[4],[6,5],[7,8,3],[9,10,11,0]]
ho pensato che il risultato dovrebbe essere solo l'aggiunta di un 0
a capo di ogni l'elenco dal delay 0
è definito come SF (0:)
.
E ancora più strano,
diag :: (ArrowCircuit a , ArrowChoice a) => a [b] [b]
diag = arr listcase >>>
arr (const []) ||| (arr id *** (diag >>> delay []) >>> arr (uncurry (:)))
runSF diag [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
[[1],[4,2],[7,5,3],[10,8,6]]
posso vedere quali sono diag
e mapA (delay 0)
fare, ma non riesco a capire il processo di calcolo con l'utilizzo di delay
. Qualcuno può aiutarti? Grazie.
Per comprendere uno di questi è davvero necessario capire 'ArrowChoice' e in particolare l'istanza' ArrowChoice SF', che non hai incluso nel codice. 'mapA' è definito solo per le frecce che hanno un'istanza' ArrowChoice', 'mapA :: ArrowChoice a => a b c -> a [b] [c]'. Il '|||' in 'diag' è l'analogo' ArrowChoice' di '&&&' per' Arrow's. – Cirdec
Mi dispiace per aver trascurato ArrowChoice, l'ho aggiunto. È utile per il tuo commento. Grazie ~ –