Non capisco cosa sia "lifting". Dovrei prima capire le monadi prima di capire cos'è un "ascensore"? (Sono completamente ignorante anche sulle monadi :) O qualcuno può spiegarmelo con parole semplici?Che cos'è il "sollevamento" in Haskell?
risposta
Il sollevamento è più un modello di progettazione che un concetto matematico (anche se mi aspetto che qualcuno qui intorno ora mi smentisca mostrando come gli ascensori sono una categoria o qualcosa del genere).
In genere si dispone di un tipo di dati con un parametro. Qualcosa di simile
data Foo a = Foo { ...stuff here ...}
Supponiamo si scopre che un sacco di usi di Foo
prendere tipi numerici (Int
, Double
, ecc) e si mantiene dover scrivere codice che scarta questi numeri, aggiunge o li moltiplica, e poi li avvolge indietro su. Puoi cortocircuitarlo scrivendo il codice unwrap-and-wrap una volta. Questa funzione viene tradizionalmente chiamato un "lift", perché assomiglia a questo:
liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
In altre parole si dispone di una funzione che prende una funzione a due argomenti (come ad esempio l'operatore (+)
) e lo trasforma in funzione equivalente per Foos.
Così ora si può scrivere
addFoo = liftFoo2 (+)
Edit: ulteriori informazioni
Ovviamente si può avere liftFoo3
, liftFoo4
e così via. Tuttavia questo spesso non è necessario.
Inizia con l'osservazione
liftFoo1 :: (a -> b) -> Foo a -> Foo b
Ma questo è esattamente lo stesso di fmap
.Quindi, piuttosto che liftFoo1
si può scrivere
instance Functor Foo where
fmap foo = ...
Se si vuole veramente completa regolarità si può quindi dire che
liftFoo1 = fmap
Se si può fare Foo
in un funtore, forse si può rendere un funtore applicativo. In realtà, se si può scrivere liftFoo2
quindi l'istanza applicativa appare così:
import Control.Applicative
instance Applicative Foo where
pure x = Foo $ ... -- Wrap 'x' inside a Foo.
(<*>) = liftFoo2 ($)
Il (<*>)
operatore per Foo ha il tipo
(<*>) :: Foo (a -> b) -> Foo a -> Foo b
Si applica la funzione avvolto al valore avvolto. Pertanto, se è possibile implementare liftFoo2
, è possibile scriverlo in termini di esso. In alternativa è possibile implementare direttamente e non perdere tempo con liftFoo2
, poiché il modulo Control.Applicative
comprende
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
e allo stesso modo ci sono liftA
e liftA3
. Ma in realtà non li uso molto spesso perché non v'è un altro operatore
(<$>) = fmap
Questo consente di scrivere:
result = myFunction <$> arg1 <*> arg2 <*> arg3 <*> arg4
Il termine myFunction <$> arg1
restituisce una nuova funzione avvolto in Foo. Questo a sua volta può essere applicato all'argomento successivo utilizzando (<*>)
e così via. Quindi ora invece di avere una funzione di sollevamento per ogni area, hai solo una catena di applicazioni.
Probabilmente vale la pena ricordare che gli ascensori devono rispettare le leggi standard 'lift id == id' e' lift (f. G) == (lift f). (ascensore g) '. –
Gli ascensori sono effettivamente "una categoria o qualcosa". Carlos ha appena elencato le leggi di Functor, dove 'id' e' .' sono la composizione di freccia e freccia di identità di alcune categorie, rispettivamente. Di solito quando si parla di Haskell, la categoria in questione è "Hask", le cui frecce sono funzioni di Haskell (in altre parole, 'id' e' .' si riferiscono alle funzioni di Haskell che conosci e ami). –
Mi piace il modo in cui si inizia citando un tipo con un parametro. Questa è l'idea più importante di Monad. Non riesco ancora a credere che nel libro: haskell del mondo reale, l'autore non ha spiegato che Monad è semplicemente una classe di tipo (controlla il capitolo sulle monadi e la programmazione di monad su quel libro) – osager
di sollevamento è un concetto che permette di trasformare una funzione in una funzione corrispondente all'interno di un altro (di solito più generale) impostando
un'occhiata a http://haskell.org/haskellwiki/Lifting
Sì, ma quella pagina inizia "Di solito iniziamo con un (fasatore) covariante ...". Non esattamente newbie friendly. –
Ma "functor" è collegato, quindi il principiante può semplicemente fare clic per vedere che cos'è un Functor. Certo, la pagina collegata non è così buona. Devo avere un account e sistemarlo. – jrockway
È un problema che ho riscontrato su altri siti di programmazione funzionale; ogni concetto è spiegato in termini di altri concetti (non familiari) fino a quando il novizio non completa il cerchio (e attorno alla curva). Deve essere qualcosa a che fare con la simpatia della ricorsione. – DNA
Cominciamo con un esempio:
> replicate 3 'a'
"aaa"
> :t replicate
replicate :: Int -> a -> [a]
> :t liftA2 replicate
liftA2 replicate :: (Applicative f) => f Int -> f a -> f [a]
> (liftA2 replicate) [1,2,3] ['a','b','c']
["a","b","c","aa","bb","cc","aaa","bbb","ccc"]
> :t liftA2
liftA2 :: (Applicative f) => (a -> b -> c) -> (f a -> f b -> f c)
liftA2
trasforma una funzione di tipi semplici in una funzione di questi tipi racchiusi in un Applicative
, ad esempio elenchi, IO
, ecc.
Un altro ascensore comune è lift
da Control.Monad.Trans
. Trasforma un'azione monadica di una monade in un'azione di una monade trasformata.
In generale, gli ascensori "sollevano" una funzione/azione in un tipo "avvolto".
Il modo migliore per capire questo, e le monade ecc. E per capire perché sono utili, è probabilmente quello di codificarlo e usarlo. Se c'è qualcosa che hai codificato in precedenza che ritieni possa trarre beneficio da questo (cioè questo renderà il codice più breve, ecc.), Provalo e afferrerai facilmente il concetto.
Paul e yairchu sono entrambe buone spiegazioni.
Vorrei aggiungere che la funzione che si sta sollevando può avere un numero arbitrario di argomenti e che non devono essere dello stesso tipo. Ad esempio, si potrebbe anche definire un liftFoo1:
liftFoo1 :: (a -> b) -> Foo a -> Foo b
In generale, il sollevamento delle funzioni che richiedono 1 argomento viene catturato nella classe tipo Functor
, e l'operazione di sollevamento è chiamato fmap
:
fmap :: Functor f => (a -> b) -> f a -> f b
Notare la somiglianza con il tipo di liftFoo1
. Infatti, se si dispone liftFoo1
, è possibile effettuare Foo
un'istanza di Functor
:
instance Functor Foo where
fmap = liftFoo1
Inoltre, la generalizzazione di sollevamento ad un numero arbitrario di argomenti è chiamato stile applicativa. Non preoccuparti di immergerti in questo fino a quando non coglierai le funzioni con un numero fisso di argomenti. Ma quando lo fai, Learn you a Haskell ha un buon capitolo su questo. Il Typeclassopedia è un altro documento valido che descrive Functor e Applicativo (così come altre classi di tipi, scorrere verso il basso nel capitolo a destra in quel documento).
Spero che questo aiuti!
Secondo this shiny tutorial, un funtore è qualche contenitore (come Maybe<a>
, List<a>
o Tree<a>
che può memorizzare elementi di qualche altro tipo, a
). Ho usato la notazione Java generica, <a>
, per il tipo di elemento a
e penso agli elementi come bacche sull'albero Tree<a>
. Esiste una funzione fmap
, che accetta una funzione di conversione degli elementi, a->b
e il contenitore functor<a>
. Si applica a->b
a ogni elemento del contenitore convertendolo in modo efficace in functor<b>
. Quando viene fornito solo il primo argomento, a->b
, fmap
attende lo functor<a>
. Cioè, fornire a->b
da solo trasforma questa funzione a livello di elemento nella funzione functor<a> -> functor<b>
che opera sui contenitori. Questo è chiamato sollevamento della funzione. Poiché il contenitore è anche chiamato un functor, i Functional piuttosto che Monads sono un prerequisito per il sollevamento. Le monadi sono un po '"parallele" al sollevamento. Entrambi si basano sulla nozione di Functor e fanno f<a> -> f<b>
. La differenza è che il sollevamento utilizza a->b
per la conversione mentre Monad richiede all'utente di definire a -> f<b>
.
Ti ho dato un segno di spunta, perché "un funtore è un contenitore" è un'esca infuocata alla troll. Esempio: funzioni da alcuni 'r' a un tipo (usiamo' c' per varietà), sono Functors. Non "contengono" alcun 'c'. In questo caso, fmap è una composizione di funzioni, che utilizza una funzione 'a -> b' e una' r -> a', per darti una nuova funzione 'r -> b'. Ancora nessun contenitore. Inoltre, se potessi, lo annoterei di nuovo per la frase finale. – BMeph
Inoltre, 'fmap' è una funzione, e non" aspetta "nulla; Il "contenitore" essendo un Functor è l'intero punto di sollevamento. Inoltre, le Monade sono, semmai, una doppia idea di sollevamento: una Monade ti consente di usare qualcosa che è stato sollevato un numero positivo di volte, come se fosse stato sollevato una sola volta - questo è meglio conosciuto come _flattening_. – BMeph
@BMeph "Aspettare", "aspettarsi", "anticipare" sono i sinonimi. Dicendo "la funzione aspetta" intendevo "la funzione anticipa". – Val
- 1. Istanza di classe di sollevamento in Haskell
- 2. È possibile codificare una funzione generica di "sollevamento" in Haskell?
- 3. sollevamento una funzione di ordine superiore in Haskell
- 4. Sollevamento eccezioni in Rcpp
- 5. Sollevamento implicito in scala
- 6. sollevamento variabile
- 7. JavaScript 'sollevamento'
- 8. In che modo il sollevamento (in un contesto di programmazione funzionale) si riferisce alla teoria delle categorie?
- 9. Funzioni di sollevamento in scala
- 10. Moq'ing il sollevamento di eventi più volte
- 11. Evitare il sollevamento con i trasformatori Monad
- 12. Esiste un CMS per il sollevamento?
- 13. Correttezza di implicita sollevamento
- 14. pow() sollevamento a float
- 15. Che cosa significa (== ""), in Haskell?
- 16. Servizio REST di sollevamento che non riconosce la richiesta PUT
- 17. Funzione Haskell che restituisce il tipo esistenziale
- 18. Javascript sollevamento in Chrome e Firefox
- 19. Sicurezza di sollevamento e tipo
- 20. Calcolo del valore di sollevamento
- 21. Che cosa significa il doppio backslash \\ in Haskell?
- 22. Che cos'è una "scintilla" in Haskell
- 23. Che cos'è ((->) t) in haskell?
- 24. Haskell: calcolo "in una monade" - che significa?
- 25. Il tipo letterale in Haskell
- 26. trucchi per Typeclass generalizzata funzione multi-parametro sollevamento
- 27. Perché le variabili di sollevamento JavaScript?
- 28. Sollevamento dell'eccezione incorporata con messaggio predefinito in python
- 29. Confusione con le funzioni di sollevamento in Scala
- 30. Che cos'è il "|" per una definizione di classe Haskell?
Forse utile, forse no: http://www.haskell.org/haskellwiki/Lifting – kennytm