Veuillez prendre un coup d'oeil dans http://www.haskell.org/yampa/AFPLectureNotes.pdfqui explique comment les Flèches de travail en PRF.
2-tuples sont utilisés dans la définition de Flèches, parce que c'est nécessaire pour représenter un arrowized fonction prenant 2 arguments.
En fibre de verre, les constantes et les variables sont souvent représentés comme des flèches qui ignore son "entrée", par exemple
twelve, eleven :: Arrow f => f p Int
twelve = arr (const 12)
eleven = arr (const 11)
Fonction des applications sont alors transformées en des compositions (>>>
):
# (6-) 12
arr (6-) <<< twelve
Maintenant, comment faire tourner un 2-fonction d'argument en flèche? Par exemple
(+) :: Num a => a -> a -> a
en raison de nourrissage que l'on peut traiter cela comme une fonction retournant une fonction. Donc
arr (+) :: (Arrow f, Num a) => f a (a -> a)
maintenant, nous allons l'appliquer à une constante
arr (+) -- # f a (a -> a)
<<< twelve -- # f b Int
:: f b (Int -> Int)
+----------+ +-----+ +--------------+
| const 12 |----> | (+) | == | const (+ 12) |
+----------+ +-----+ +--------------+
hé, attendez, ça ne fonctionne pas. Le résultat est toujours une flèche qui retourne une fonction, mais nous nous attendons à quelque chose qui s'apparente à l' f Int Int
. Nous remarquons que nourrissage échoue en Flèche parce que seule la composition est autorisé. Par conséquent, nous devons uncurry la fonction première
uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry (+) :: Num a => (a, a) -> a
Ensuite, nous avons la flèche
(arr.uncurry) (+) :: (Num a, Arrow f) => f (a, a) a
Le 2-n-uplet se pose à cause de cela. Puis le tas de fonctions comme &&&
sont nécessaires pour faire face à ces 2-tuples.
(&&&) :: f a b -> f a d -> f a (b, d)
ensuite, l'ajout peut être correctement effectuée.
(arr.uncurry) (+) -- # f (a, a) a
<<< twelve -- # f b Int
&&& eleven -- # f b Int
:: f b a
+--------+
|const 12|-----.
+--------+ | +-----+ +----------+
&&&====> | (+) | == | const 23 |
+--------+ | +-----+ +----------+
|const 11|-----'
+--------+
(Maintenant, pourquoi n'avons-nous pas besoin des choses comme &&&&
, pour les 3-n-uplets pour les fonctions ayant 3 arguments? Parce qu'un ((a,b),c)
peut être utilisé à la place.)
Edit: a Partir de John Hughes, le papier original de Généraliser les Monades de Flèches, il indique la raison que
4.1 les Flèches et les Paires
Cependant, même si dans le cas de monades les opérateurs return
et >>=
sont tout ce que nous devons commencer à écrire du code utile, pour les flèches analogues des opérateurs arr
et >>>
ne sont pas suffisantes. Même le simple monadique fonction d'addition que nous avons vu plus tôt
add :: Monad m => m Int -> m Int -> m Int
add x y = x >>= \u -> (y >>= \v -> return (u + v))
ne peut pas encore être exprimé dans une forme de flèche. Prise de dépendance sur une entrée explicite, on voit qu'une définition analogue devrait prendre la forme
add :: Arrow a => a b Int -> a b Int -> a b Int
add f g = ...
où nous devons combiner f
et g
dans la séquence. La seule séquençage de l'opérateur est disponible >>>
, mais f
et g
n'ont pas le droit de types composés. En effet, l' add
fonction des besoins pour enregistrer l'entrée de type b
à travers le calcul de l' f
, de manière à être en mesure de fournir la même entrée d' g
. De même, le résultat d' f
doivent être enregistrées à travers le calcul de l' g
, de sorte que les deux résultats peuvent éventuellement être ajoutés et retourné. La flèche combinators jusqu'à présent introduit de nous donner aucun moyen d'enregistrer une valeur dans un autre calcul, et donc nous n'avons pas d'autre alternative que d'introduire un autre combinator.