2009-02-13 9 views
7

Soy un novato Haskell, aunque tenía una experiencia anterior de Lisp/Scheme. En este momento estoy viendo los ejemplos del SICP y tratando de implementarlos en Haskell para obtener más experiencia práctica. En la conferencia 3b, los autores presentan una función para calcular simbólicamente los derivados. Contiene, entre otras, las siguientes líneas:Examinando las partes internas de las funciones en Haskell

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

Además, en la conferencia, algunas de las funciones más se definen:

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

¿Hay una manera de hacer lo mismo en Haskell, es decir, comprobar si hay atomicidad y equivalencia simbólica a alguna otra función? O más general, ¿cuáles son los medios para "desmontar" las funciones en Haskell?

Respuesta

4

Los ejemplos de su esquema en realidad no examinan las funciones del esquema. Recientemente he hecho un poco de diferenciación simbólica en Haskell sobre los valores del siguiente tipo:

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

En lugar de discriminar usando atom? o eq? utiliza case (u otra coincidencia de patrones) y ==.

+0

¿Qué hay de la evaluación de sus datos Exp (por lo que yo entiendo, esto es en última instancia, una lista)? –

+0

En realidad, no necesitaba una función eval; Estaba usando diferenciación simbólica para emitir código C. Si quieres escribir uno y tienes problemas, publica una pregunta :-) –

1

No creo que puedas hacer eso. Lisp es homoiconic, Haskell no lo es.

Sin embargo, Google adicional apareció Liskell, que es (?) Un híbrido interesante.

+1

Sí, pensé en homoiconicidad. Sin embargo, no necesito que las funciones, los datos y el programa se representen de la misma manera. El hecho de que la representación de los tipos de datos algebraicos sea diferente a la del programa no me limita a la hora de deconstruirlos. –

6

En primer lugar, aunque el SICP es excelente, recomendaría que no aprenda Haskell. (#) Parte de la dificultad en esta pregunta se debe a esto.

En Lisp/Scheme, un 'function' se considera un fragmento de código, y examinar una función simplemente significa examinar su código. En Haskell, un 'function' significa algo más cercano a su definición matemática, como un mapa de un conjunto A a un conjunto B. Entonces, por ejemplo, tiene sentido, en el contexto de Lisp, comparar dos funciones: simplemente compare su código. (¿Pero son (x+y)^2 y x^2+2*x*y+y^2 funciones diferentes?) En Haskell, depende de si existe un procedimiento constructivo para determinar la igualdad para la clase de funciones que está considerando.

De forma similar, como en su pregunta, en Lisp/Scheme, escribiría una función "derivar" que diferencie correctamente cuando se le den expresiones, y solo errores o devuelve basura en entradas arbitrarias. Bajo el sistema de tipos de Haskell, esto es (AFAIK) imposible de hacer, porque -si lo piensas- no existe diferenciación de una entrada arbitraria: solo puedes diferenciar una Expresión (o posiblemente una clase más general, pero aún no todo). Así como en la respuesta de Norman Ramsey, se define primero un tipo de "Expresión" (o clase de tipo), lo que es muy sencillo de hacer, y luego escribir la función

derive :: Expression -> Expression 

que desmonta un Expression usando las construcciones de patrones de coincidencia (o algo más dependiendo de cómo se crearon Expression s).


(#): La razón es que SICP tiene una filosofía completamente diferente, que implica el uso de un lenguaje de programación sin tipo y el fomento de la falta de distinción entre el código y los datos. Si bien hay algunos méritos para el argumento "código = datos" (por ejemplo, el hecho de que en la arquitectura von Neumann que utilizamos, "todo es 0 y 1 de todos modos"), no es necesariamente una buena forma de razonar o modelar problemas.(Véase Philip Wadler de Why Calculating is Better than Scheming para más información sobre esto.) Si desea leer un libro con un sabor Haskell funcional en lugar de un Real World uno, tal vez de Haskell: The Craft of Functional Programming Simon Thompson o Richard Bird de Introduction to Functional Programming using Haskell son mejores opciones.

Cuestiones relacionadas