Currying 3 Arguments in Haskell

Sto avendo problemi con la conversione di una funzione per rimuovere tre argomenti in Haskell.

Disclaimer: Not Coursework, mi è stata posta questa domanda da qualcuno alle prese con questo oggi e mi ha infastidito.

I tipi / funzioni personalizzati che ci sono stati dati erano (possono solo ricordare tipi)

type MyThing = (Char, String) type MyThings = [MyThing] funcA :: MyThings -> String -> String funcB :: MyThings -> String -> Int -> String 

Abbiamo iniziato con:

 funcB as str n = iterate (funcA as) str !! n 

E lo riduci come segue:

     funcB as str n = iterate (funcA as) str !! n funcB as str = (!!) . (iterate (funcA as)) str funcB as = (!!) . (iterate (funcA as)) funcB as = (!!) . (iterate . funcA) as 

    Quindi, bloccato. Semplicemente non riusciamo a capire come evitare di usare l’ultimo argomento. So di aver visto una situazione simile da qualche parte prima e c’era una soluzione.

    Sperando che un genio di Haskell possa indicare perché sono un idiota …

    Tutto ciò di cui hai bisogno sono le tre seguenti “leggi” delle sezioni dell’operatore:

     (a `op` b) = (a `op`) b = (`op` b) a = op ab (1) (2) (3) 

    in modo che l’operando entri nello slot libero vicino all’operatore.

    Per (.) Questo significa che: (a . b) = (a .) b = (. b) a = (.) ab . Così,

     f (gx) y !! n = (!!) (f (gx) y) n by (3) = ((!!) . f (gx)) yn = ((!!) . (f . g) x) yn = ((!!) .) ((f . g) x) yn by (1) = (((!!) .) . (f . g)) xyn = (((!!) .) . f . g) xyn 

    Dovresti eseguire tutte le trasformazioni prive di point point con le quali ti senti a tuo agio, in modo che l’espressione risultante sia ancora leggibile per te , e in effetti più chiara dell’originale. Lo strumento “pointfree” può a volte produrre risultati illeggibili.

    È perfettamente OK fermarsi nel mezzo. Se è troppo difficile per te completarlo manualmente, probabilmente sarà difficile leggerlo anche tu.

    ((a .) . b) xy = (a .) (bx) y = (a . bx) y = a (bxy) è uno schema comune che imparerai rapidamente a riconoscere immediatamente. Quindi l’espressione sopra può essere letta abbastanza facilmente come

     (!!) ((f . g) xy) n = f (gx) y !! n 

    considerando che (.) è associativo:

     (a . b . c) = ((a . b) . c) = (a . (b . c)) 
     funcB = ((!!) .) . iterate . funcA 

    Penso che tu abbia fatto tutto il lavoro duro, e c’era rimasto solo un piccolo passo.

    Puoi farlo automaticamente con pointfree . Vedi la pagina HaskellWiki

    Come si dice nel file github , una volta installato, puoi modificare il file ghci.conf o .ghci con la linea

     :def pf \str -> return $ ":! pointfree \"" ++ str ++ "\"" 

    e poi in ghci quando scrivi

     :pf funcB as = (!!) . (iterate . funcA) as 

    o anche

     :pf funcB as str n = iterate (funcA as) str !! n 

    ottieni

     funcB = ((!!) .) . iterate . funcA 

    L’osservazione chiave per me è che gli operatori infissi possono essere prefissi scritti:

     funcB as = (!!) . (iterate . funcA) as funcB as = (.) (!!) ((iterate . funcA) as) 

    Una volta che sei arrivato qui, hai una mezza possibilità di riconoscere che questa è una composizione, con (.) (!!) come primo argomento e iterate . funcA iterate . funcA come secondo argomento:

     funcB as = ( ((.) (!!)) . (iterate . funcA) ) as 

    Ora è chiaro come semplificare questo; dopo, ci sono molte scelte estetiche su come scriverlo. Ad esempio, potremmo osservare che (.) È associativo e quindi possiamo rilasciare alcune parentesi; allo stesso modo, possiamo usare le sezioni dell’operatore per unire l’antiestetico ((.) (!!)) se pensi che sia più leggibile in questo modo.

     funcB = ( ((.) (!!)) . (iterate . funcA) ) funcB = (.) (!!) . iterate . funcA -- uncontroversial parenthesis removal funcB = ((!!) .) . iterate . funcA -- possibly controversial section rewrite 

    A proposito, non penso che l’inizio della tua derivazione sia corretto. Hai raggiunto la conclusione giusta, ma tramite passaggi intermedi sbagliati. Corretto, dovrebbe assomigliare a questo:

     funcB as str n = iterate (funcA as) str !! n funcB as str n = (!!) (iterate (funcA as) str) n funcB as str = (!!) (iterate (funcA as) str) funcB as = (!!) . iterate (funcA as)