Sono sempre interessato a imparare nuove lingue, un fatto che mi tiene sulle dita dei piedi e me (credo) un programmatore migliore fa. I miei tentativi di conquistare Haskell vanno e vengono, due volte finora, e ho deciso che era ora di provare di nuovo. Il 3 ° tempo è il fascino, giusto?applicazione Haskell funzione e strigliare
No. Rileggo i miei vecchi appunti ... e rimango deluso :-(
Il problema che mi ha fatto perdere la fiducia l'ultima volta, è stato facile: permutazioni di numeri interi cioè da un elenco di numeri interi, a un elenco delle liste - un elenco dei loro permutazioni:
[int] -> [[int]]
Questo è infatti un problema generico, in modo che sostituiscono 'int' di cui sopra con 'a', si applicherebbe comunque
dai miei appunti:
.Lo codice prima da solo, ci riesco. Evviva!
Invio la mia soluzione a un mio buon amico - Haskell guru, di solito aiuta a imparare dai guru - e mi invia questo, che mi è stato detto, "esprime il vero potere della lingua, l'uso del generico strutture per codificare le tue esigenze ". Tutto per esso, di recente ho bevuto il Kool-Aid, andiamo:
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. Rompiamo questo in giù:
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, così qui, tutto bene. Mi ci volle un minuto per capire la seconda linea di "ins", ma OK: Essa pone la prima arg in tutte le possibili posizioni nella lista. Freddo.
Ora, per capire il foldr e concatMap. nel "mondo reale Haskell", il DOT è stato spiegato ...
(f . g) x
... come un altro sintassi per ...
f (g x)
E nel codice il guru ha inviato, DOT è stato utilizzato da un foldr, con la funzione "ins", come la piega "collasso":
*Main> let g=concatMap . ins
*Main> g 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
OK, perché voglio capire come il DOT è utilizzato dal guru, provo l'espressione equivalente secondo la definizione DOT , (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]])
Cosa!?! Perché? OK, verifico la firma di concatMap, e scoprire che ha bisogno di un lambda e una lista, ma questo è solo un pensiero umano; come fa GHC a far fronte? Secondo la definizione di DOT sopra ...
(f.g)x = f(g x),
... quello che ho fatto era valido, sostituire-saggio:
(concatMap . ins) x y = concatMap (ins x y)
graffia testa ...
*Main> concatMap (ins 1) [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
Così ...La spiegazione DOT era apparentemente troppo semplicistica ... DOT deve essere abbastanza intelligente per capire che in realtà volevamo "ins" per allontanarci e "mangiare" il primo argomento - diventando così una funzione che vuole solo operare su [t] (e "intersponderli" con "1" in tutte le posizioni possibili).
Ma dove è stato specificato? Come ha fatto GHC sapeva di fare questo, quando abbiamo invocato:
*Main> (concatMap . ins) 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
ha fatto la firma "ins" in qualche modo convogliata questo ... "mangiare il mio primo argomento" politica?
*Main> :info ins
ins :: t -> [t] -> [[t]] -- Defined at b.hs:1:0-2
Non vedo niente di speciale - "ins" è una funzione che prende un 't', un elenco di 't', e procede a creare una lista con tutte le "interspersals". Niente su "mangia la tua prima discussione e mangiala via".
Quindi ... sono sconcertato. Capisco (dopo un'ora di osservazione del codice!) Cosa succede, ma ... Dio onnipotente ... Forse GHC fa dei tentativi per vedere quanti argomenti può "staccare"?
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)
Ancora una volta - yikes ...
E siccome sono sempre confrontando le lingue che sto imparando con quello che so già, come sarebbe "ins" guardare in Python?
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]]
Sii onesto, ora ... che è più semplice?
Voglio dire, so di essere un principiante in Haskell, ma mi sento un idiota ... Guardando 4 righe di codice per un'ora, e finendo per assumere che il compilatore ... prova varie interpretazioni fino a quando trova qualcosa che "fa clic"?
citare arma letale: "Sono troppo vecchio per questo" ...
Si potrebbe voler aggiungere una sezione TLDR per i pigri ... – ChaosPandion
Non capisco Haskell, ma ragazzo sono d'accordo con quello che hai detto. +1. –
Sono un po 'confuso dal confronto con Python. Il codice python che hai mostrato è solo per la funzione 'ins', giusto? Ma la funzione 'ins' non era quella che hai trovato complicata nella versione di Haskell - era concatMap e questa è la parte che hai lasciato nella tua versione python. – sepp2k