检查Haskell中函数的内部

时间:2009-02-13 22:19:07

标签: haskell functional-programming sicp

我是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中“反汇编”函数的手段是什么?

3 个答案:

答案 0 :(得分:6)

首先,虽然SICP很棒,但我会建议不要学习Haskell。(#)这个问题的一些难点源于此。

在Lisp / Scheme中,'function'被认为是一段代码,检查函数只是意味着检查它的代码。在Haskell中,'function'表示更接近其数学定义的东西,如从集合A到集合B的映射。例如,在Lisp上下文中,比较两个函数是有意义的:只需比较它们码。 (但是(x+y)^2x^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的Why Calculating is Better than Scheming。)如果您想阅读具有功能性而不是Real World的Haskell书籍,可能是Simon Thompson的Haskell: The Craft of Functional Programming或Richard Bird的{{ 3}}是更好的选择。

答案 1 :(得分:4)

您的Scheme示例实际上并未检查Scheme函数。我最近在Haskell中对以下类型的值进行了一些符号区分:

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

您可以使用atom?(或其他模式匹配)和eq?,而不是使用case==进行区分。

答案 2 :(得分:1)

我认为你不能那样做。 Lisp是homoiconic,Haskell不是。

然而,进一步的谷歌搜索出现了Liskell,这是(?)一个有趣的混合体。