Quindi sto provando a scrivere un parser complesso, usando solo Applicativo (il parser in questione non implementa nemmeno Monad).Lottare con l'analisi applicativa
Per parser banali, questo è abbastanza facile. Per quelli non banali ... non così tanto. L'interfaccia applicativa sembra forzarti violentemente a scrivere tutto in uno stile senza punti. Questo è estremamente difficile da affrontare.
Si consideri, ad esempio:
call = do
n <- name
char '('
trim
as <- sepBy argument (char ',' >> trim)
char ')'
trim
char '='
r <- result
return $ Call {name = n, args = as, result = r}
Ora proviamo a scrivere che l'utilizzo di applicativi:
call =
(\ n _ _ as _ _ _ _ r -> Call {name = n, args = as, result = r}) <$>
name <*>
char '(' <*>
trim <*>
sepBy argument (const const() <$> char ',' <*> trim) <*>
char ')' <*>
trim <*>
char '=' <*>
trim <*>
result
applicativo ha costretti me per mettere le associazioni variabile molto lontano dal punto in cui l'attuale parser è. (Ad esempio, cercare di confermare che as
è in realtà destinata a sepBy argument ...
, non è affatto facile verificare che non ho il conteggio sbagliato di _
modelli!)
Un'altra cosa molto poco intuitivo è che <*>
applica una funzione di un valore, ma *>
e <*
sono solo sequenze puri. Ciò ha richiesto età per avvolgere la mia mente. Diversi nomi di metodi avrebbero reso questo molto, molto più chiaro. (Ma Monade sembra aver afferrato >>
e <<
, purtroppo.) Sembra che questi possono essere impilati, ottenendo le cose come
exit =
"EXIT:" *>
trim *>
name <*
char '(' <*
trim <*
char ')' <*
trim
E 'piuttosto non ovvio che si può fare questo. E, per me, questo codice in realtà non è terribilmente leggibile. Ancora più importante, non ho ancora capito come gestire la raccolta di più valori mentre si eliminano più valori.
In tutto, mi trovo a desiderare di poter usare solo la notazione! In realtà non ho bisogno di cambiare gli effetti in base ai risultati precedenti; Io non lo ho bisogno del il potere di Monad. Ma la notazione è molto più leggibile. (Continuo a chiedermi se sarebbe effettivamente possibile implementarlo, puoi sintatticamente dire quando un particolare blocco può essere trasformato meccanicamente in applicativo?)
Qualcuno conosce un modo per aggirare questi problemi? In particolare, come posso spostare le associazioni delle variabili più vicino al parser a cui si legano?
Suppongo che attendere ['Applicativo-Do'] (https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo) sia troppo difficile per alcune persone;) –
Non penso' << 'esiste, almeno non in' base'. – Rufflewind
@BartekBanachewicz Applicativo-do ... La richiesta di funzione esiste già. Immagino sia vero; se riesci a pensarci, è già su Internet da qualche parte. – MathematicalOrchid