2016-07-13 11 views
1

Ich hatte eine Frage zu einer der Implementierungen der Duplikatfunktion, wie in 99 Haskell Questions (https://wiki.haskell.org/99_questions/Solutions/14) beschrieben.99 Haskell Questions # 14

Eine der Lösungen verwendet die Listeninstanz von Applicative. Diese besondere Lösung ist

duplicate = (<**> [id,id]) 

Ich habe mich gefragt, warum, wenn ich versuchte, Duplikat zu implementieren, anstatt als

duplicate' = ([id,id] <*>) 

I

duplicate' [1,2,3] = [1,2,3,1,2,3] 

Statt [1,1,2,2 erhalten , 3,3].

Danke!

Antwort

1

f <*> v ist nicht dasselbe wie v <**> f. Wir können dies mit Either:

import Control.Applicative ((<*>),(<**>)) 

f :: Either String (a -> b) 
f = Left "f evaluated first" 

v :: Either String a 
v = Left "v evaluated first" 

showE :: Show a => Either a b -> String 
showE (Left x) = "Left: " ++ show x 
showE (Right _) = "Right" 

printE = putStrLn . showE 

main = do 
    printE (f <*> v) 
    printE (v <**> f) 

Ergebnis:

Left: "f evaluated first" 
Left: "v evaluated first" 

Denken Sie daran, <*> Sequenzen Aktionen.

2
[f, g] <*> [x, y] 

entspricht

[ h w | h <- [f, g], w <- [x, y] ] 

Daher wir

bekommen ist
[ f x, f y, g x, g y ] 

Im Vergleich

[x, y] <**> [f, g] 

entspricht

Daher
[ h w | w <- [x, y], h <- [f, g] ] 

, erhalten wir

[ f x, g x, f y, g y ] 

Das entsandte Beispiel folgt in ähnlicher Weise.

Denken Sie daran, dass Anwendungskombinatoren zuerst die Wirkung des ersten Arguments ausführen. Der "Effekt" ist hier grob gesagt "ein Element aus der Liste ziehen".