Ich bin immer daran interessiert, neue Sprachen zu lernen, eine Tatsache, die mich auf Trab hält und macht mich (glaube ich) ein besserer Programmierer. Meine Versuche, Haskell zu erobern, kamen und gingen - zweimal so weit - und ich beschloss, dass es an der Zeit war, es noch einmal zu versuchen. 3. Mal ist der Charme, oder?Haskell Funktion Anwendung und currying
Nein. Ich lese meine alten Notizen noch einmal ... und werde enttäuscht :-(
Das Problem, das mich letztes Mal das Vertrauen verloren hat, war einfach: Permutationen von ganzen Zahlen. dh von einer Liste von ganzen Zahlen, zu einer Liste von Listen - eine Liste ihrer Permutationen:
[int] -> [[int]]
Dies ist in der Tat ein allgemeines Problem, würde gelten, so 'int' oben mit 'a', ersetzt noch
aus meinen Notizen:
.Ich code es zuerst auf eigene Faust, es gelingt mir. Hurray!
Ich sende meine Lösung an einen guten Freund von mir - Haskell Guru, es hilft normalerweise, von Gurus zu lernen - und er sendet mir das, was mir gesagt wird, "drückt die wahre Kraft der Sprache, den Gebrauch von Generika aus Einrichtungen, um Ihre Bedürfnisse zu kodieren ". Alles für es, ich trank vor kurzem die Kool-Aid, lass uns gehen:
permute :: [a] -> [[a]]
permute = foldr (concatMap.ins) [[]]
where ins x [] = [[x]]
ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]
Hmm. Lassen Sie uns dies aufgliedern:
bash$ cat b.hs
ins x [] = [[x]]
ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]
bash$ ghci
Prelude> :load b.hs
[1 of 1] Compiling Main (b.hs, interpreted)
Ok, modules loaded: Main.
*Main> ins 1 [2,3]
[[1,2,3],[2,1,3],[2,3,1]]
OK, so weit, so gut. Nahm mich eine Minute, um die zweite Zeile von "ins" zu verstehen, aber OK: Es platziert den ersten arg in allen möglichen Positionen in der Liste. Cool.
Nun, um die foldr und concatMap zu verstehen. in der "realen Welt Haskell" wurde die DOT erklärt ...
(f . g) x
... als nur eine andere Syntax für ...
f (g x)
Und im Code der Guru geschickt wurde DOT verwendet von einem foldr, mit der „In“ Funktion als fold „Kollaps“:
*Main> let g=concatMap . ins
*Main> g 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
OK, da ich verstehen will, wie die DOT vom Guru verwendet wird, versuche ich, den äquivalenten Ausdruck gemäß der DOT-Definition , (f. g) x = f (gx) ...
*Main> concatMap (ins 1 [[2,3]])
<interactive>:1:11:
Couldn't match expected type `a -> [b]'
against inferred type `[[[t]]]'
In the first argument of `concatMap', namely `(ins 1 [[2, 3]])'
In the expression: concatMap (ins 1 [[2, 3]])
In the definition of `it': it = concatMap (ins 1 [[2, 3]])
Was!?! Warum? OK, ich überprüfe die concatMap-Signatur und stelle fest, dass sie ein Lambda und eine Liste benötigt, aber das ist nur ein menschliches Denken; Wie bewältigt GHC? Nach der Definition von DOT oben ...
(f.g)x = f(g x),
... was ich war gültig war, ersetzen weise:
(concatMap . ins) x y = concatMap (ins x y)
Kopf verkratzt ...
*Main> concatMap (ins 1) [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
So ...Die DOT-Erklärung war anscheinend zu simpel ... DOT muss irgendwie klug genug sein, um zu verstehen, dass wir tatsächlich "ins" wollten, um curri-ed weg zu bekommen und das erste Argument "essen" und so eine Funktion werden, die nur will operieren auf [t] (und "durchsetzen" sie mit "1" in allen möglichen Positionen).
Aber wo wurde das angegeben? Wie kam wußte GHC, dies zu tun, wenn wir aufgerufen:
*Main> (concatMap . ins) 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
Hat das „In“ Signatur irgendwie diese vermittelt ... „essen mein erstes Argument“ Politik?
*Main> :info ins
ins :: t -> [t] -> [[t]] -- Defined at b.hs:1:0-2
Ich sehe nicht nichts besonder - „In“ ist eine Funktion, die eine ‚t‘ nimmt, eine Liste von ‚t‘ und geht eine Liste mit allen „interspersals“ zu erstellen. Nichts über "essen Sie Ihr erstes Argument und curry es weg".
Also da ... Ich bin verwirrt. Ich verstehe (nach einer Stunde, in der ich den Code anschaue!), Was vor sich geht, aber ... Gott allmächtig ... Vielleicht versucht GHC zu sehen, wie viele Argumente es "ablösen" kann?
let's try with no argument "curried" into "ins",
oh gosh, boom,
let's try with one argument "curried" into "ins",
yep, works,
that must be it, proceed)
Again - Huch ...
Und da ich immer die Sprachen bin im Vergleich mit denen ich lerne, was ich schon weiß, wie würde „In“ in Python aussehen?
a=[2,3]
print [a[:x]+[1]+a[x:] for x in xrange(len(a)+1)]
[[1, 2, 3], [2, 1, 3], [2, 3, 1]]
Sei ehrlich, jetzt ... was ist einfacher?
Ich meine, ich weiß, ich bin ein Neuling in Haskell, aber ich fühle mich wie ein Idiot ... Betrachtet 4 Zeilen Code für eine Stunde und am Ende vorausgesetzt, dass der Compiler ... verschiedene Interpretationen bis es versucht findet etwas, das "klickt"?
von tödlicher Waffe zu zitieren: „Ich bin zu alt für dieses“ ...
Vielleicht möchten Sie eine TLDR-Sektion für die faulen ... – ChaosPandion
Ich verstehe nicht, Haskell, aber Junge stimme ich mit dem, was Sie gesagt haben. +1. –
Ich bin ein wenig verwirrt durch Ihren Python-Vergleich. Der Python-Code, den du gezeigt hast, ist nur für die "ins" -Funktion, richtig? Aber die "ins" -Funktion war nicht das, was Sie in der Haskell-Version als kompliziert empfanden - die concatMap war und das ist der Teil, den Sie in Ihrer Python-Version weggelassen haben. – sepp2k