Pergunta

Eu sou um novato Haskell, embora tinha uma experiência anterior Lisp / Scheme. Agora eu estou olhando para os exemplos de SICP e tentar implementá-los em Haskell para conseguir mais experiência hands-on. Na palestra autores 3b apresentam uma função para calcular os derivados simbolicamente. Ele contém, entre outras, as seguintes linhas:

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

Além disso na palestra, mais algumas funções são definidas:

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

Existe uma maneira de fazer mesma coisa em Haskell, ou seja, cheque de atomicidade e equivalência simbólica para alguma outra função? Ou mais geral, quais são os meios de "desmontar" funções em Haskell?

Foi útil?

Solução

Seus exemplos Esquema não realmente examinar funções de esquema. Recentemente, fiz alguma diferenciação simbólica em Haskell sobre os valores do seguinte tipo:

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

Em vez de discriminar usando atom? ou eq? você usa case (ou outra correspondência de padrões) e ==.

Outras dicas

Em primeiro lugar, embora SICP é ótimo, eu recomendo contra ela para aprender Haskell. (#) Algumas das dificuldades nesta questão decorre disso.

/ Esquema Lisp em um 'função' é pensado de um pedaço de código, e examinando uma função simplesmente significa examinar seu código. Em Haskell, uma 'função' meios algo mais próximo de sua definição matemática, como um Roteiro de um conjunto um a um conjunto B. Assim, por exemplo, faz sentido, no contexto Lisp, para comparar duas funções: basta comparar o seu código. (Mas são (x+y)^2 e x^2+2*x*y+y^2 funções diferentes?) Em Haskell, isso depende se existe um procedimento construtivo para determinar a igualdade para a classe de funções que você está considerando.

Da mesma forma, como na sua pergunta, em Lisp / Scheme, você deve escrever uma função "derivam" que diferencia corretamente quando dada expressões, e apenas a erros ou retornar lixo nas entradas arbitrárias. Sob o sistema tipo de Haskell, este é (AFAIK) impossível de fazer, porque, se você pensar sobre isso, não existe tal coisa como diferenciar uma entrada arbitrária: você só pode diferenciar uma expressão (ou possivelmente uma classe mais geral, mas ainda não tudo). Assim como na resposta de Norman Ramsey, você primeiro definir um tipo de "Expression" (ou tipo de classe), que é muito simples de fazer, e, em seguida, escrever a função

derive :: Expression -> Expression

que desmonta uma Expression usando as construções de correspondência de padrão (ou qualquer outra coisa, dependendo de como Expressions foram construídos).


(#): A razão é que SICP tem uma filosofia completamente diferente, que envolve o uso de uma linguagem de programação untyped e incentivando a falta de distinção entre o código e os dados. Embora haja algum mérito ao "code = dados" argumento (por exemplo, o fato de que na arquitetura von Neumann que usamos, "tudo é 0s e 1s de qualquer maneira"), não é necessariamente uma boa maneira de raciocinar sobre ou modelagem de problemas. (See de Philip Wadler Por Cálculo é melhor do que Scheming para saber mais sobre isso.) Se você quiser ler um livro Haskell com um sabor funcional em vez de um real World um, talvez de Simon Thompson Haskell: The Craft da programação funcional < Introdução / a> ou Richard Bird para programação funcional Haskell usando são melhores escolhas.

Eu não acho que você pode fazer isso. Lisp é homoiconic , Haskell não é.

No entanto, ainda Googling apareceu Liskell , que é (?) Um híbrido interessante.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top