Domanda

Sono un principiante di Haskell, anche se ho avuto una precedente esperienza con Lisp/Scheme.In questo momento sto guardando gli esempi di SICP e sto cercando di implementarli in Haskell per ottenere più esperienza pratica.Nella lezione 3b gli autori presentano una funzione per calcolare simbolicamente le derivate.Contiene, tra le altre, le seguenti righe:

(define (deriv exp var)
    (cond ((constant? exp var) 0)
          ((same-var? exp var) 1)
; ...

Più avanti nella lezione verranno definite altre funzioni:

(define (constant? exp var)
    (and (atom? exp)
         (not (eq? exp var))))

C'è un modo per fare la stessa cosa in Haskell, ad es.verificare l'atomicità e l'equivalenza simbolica con qualche altra funzione?O più in generale, quali sono i mezzi per "disassemblare" le funzioni in Haskell?

È stato utile?

Soluzione

I tuoi esempi di Scheme in realtà non esaminano le funzioni di Scheme.Recentemente ho fatto alcune differenziazioni simboliche in Haskell su valori del seguente tipo:

data Exp a = Lit a
           | Exp a :*: Exp a
           | Exp a :+: Exp a
           | Var String
  deriving Eq

Invece di discriminare usando atom? O eq? usate case (o altro modello di corrispondenza) e ==.

Altri suggerimenti

In primo luogo, sebbene SICP sia ottimo, lo sconsiglierei per imparare Haskell.(#) Parte della difficoltà in questa domanda deriva da questo.

In Lisp/Scheme, a 'funzione' è pensato come un pezzo di codice ed esaminare una funzione significa semplicemente esaminarne il codice.In Haskell, a 'funzione' significa qualcosa di più vicino alla sua definizione matematica, come una mappa da un insieme A a un insieme B.Quindi, ad esempio, ha senso, nel contesto Lisp, confrontare due funzioni:basta confrontare il loro codice.(Ma lo sono (x+y)^2 E x^2+2*x*y+y^2 funzioni diverse?) In Haskell, dipende se esiste una procedura costruttiva per determinare l'uguaglianza per la classe di funzioni che stai considerando.

Allo stesso modo, come nella tua domanda, in Lisp/Scheme, scriveresti una funzione "derivata" che differenzia correttamente quando vengono fornite espressioni e semplicemente genera errori o restituisce spazzatura su input arbitrari.Con il sistema di tipi di Haskell, questo è (per quanto ne so) impossibile da fare, perché, se ci pensi, non esiste qualcosa come differenziare un input arbitrario:puoi differenziare solo un'espressione (o eventualmente una classe più generale, ma non ancora tutto).Quindi, come nella risposta di Norman Ramsey, prima definisci un tipo "Espressione" (o classe di tipo), che è molto semplice da fare, e poi scrivi la funzione

derive :: Expression -> Expression

che smonta un Expression utilizzando i costrutti di corrispondenza dei modelli (o qualcos'altro a seconda di come Expressions sono stati costruiti).


(#):Il motivo è che SICP ha una filosofia completamente diversa, che implica l’utilizzo di un linguaggio di programmazione non tipizzato e l’incoraggiamento alla mancanza di distinzione tra codice e dati.Anche se c'è qualche merito nell'argomento "code=data" (ad es.il fatto che sull'architettura di von Neumann che utilizziamo, "tutto è comunque 0 e 1"), non è necessariamente un buon modo di ragionare o modellare i problemi.(Vedi Philip Wadler Perché calcolare è meglio che fare schemi per ulteriori informazioni al riguardo.) Se vuoi leggere un libro Haskell con un sapore funzionale invece di un Mondo reale uno, forse quello di Simon Thompson Haskell:L'arte della programmazione funzionale o di Richard Bird Introduzione alla programmazione funzionale utilizzando Haskell sono scelte migliori.

Non penso che tu possa farlo.Lisp lo è omoiconico, Haskell no.

Tuttavia, sono emerse ulteriori ricerche su Google Liskell, che è (?) un ibrido interessante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top