我是Haskell的新手,虽然有过以前的Lisp/Scheme体验.现在我正在查看SICP的示例,并尝试在Haskell中实现它们以获得更多的实践经验.在讲座3b中,作者提出了一种象征性地计算衍生物的功能.它包含以下几行:
(define (deriv exp var) (cond ((constant? exp var) 0) ((same-var? exp var) 1) ; ...
在讲座中,还定义了更多功能:
(define (constant? exp var) (and (atom? exp) (not (eq? exp var))))
有没有办法在Haskell中做同样的事情,即检查原子性和符号等价于其他函数?或者更一般的是,Haskell中"反汇编"函数的手段是什么?
首先,虽然SICP很棒,但我建议不要学习Haskell.(#)这个问题的一些难点源于此.
在Lisp/Scheme中,"函数"被认为是一段代码,而检查函数只是意味着检查它的代码.在Haskell中,"函数"意味着更接近其数学定义的东西,如从集合A到集合B的映射.例如,在Lisp上下文中,比较两个函数是有意义的:只需比较它们的代码.(但是(x+y)^2
和x^2+2*x*y+y^2
不同的函数?)在Haskell中,它取决于是否存在确定您正在考虑的函数类的相等性的构造过程.
类似地,在你的问题中,在Lisp/Scheme中,你会编写一个"derive"函数,在给定的表达式中正确区分,并且只是输出错误或在任意输入上返回垃圾.在Haskell的类型系统下,这是(AFAIK)不可能做到的,因为 - 如果你想到它 - 没有区分任意输入的东西:你只能区分一个表达式(或者可能是一个更普通的类,但仍然没有一切).因此,在Norman Ramsey的回答中,您首先定义一个"表达式"类型(或类型类),这很简单,然后编写函数
derive :: Expression -> Expression
反汇编Expression
使用模式匹配结构(或其他东西取决于如何Expression
构建).
(#):原因是SICP有一个完全不同的哲学,它涉及使用无类型编程语言并鼓励代码和数据之间缺乏区别.虽然"code = data"参数有一些优点(例如,在我们使用的von Neumann架构中,"无论如何都是0和1"),但它不一定是推理或建模问题的好方法.(参见Philip Wadler的" 为什么计算比计划更好 "更多内容.)如果你想阅读具有功能性而非真实世界的Haskell书籍,也许是Simon Thompson的Haskell:功能编程工艺或Richard Bird