什么是任何序列计算所需的最小序列“基元”?

时间:2009-05-11 10:32:50

标签: c# functional-programming scheme

我在翻译中写了一个类似Scheme的程序。类似Scheme的解释器应该与任何实现IEnumerable的对象一起工作,这似乎很自然。

解释器不允许突变 - 没有暴露副作用的功能。

因为IEnumerable不可复制,(参见here),我无法使用car和cdr有效地在列表上实现迭代。

为了让任何“更高阶”的东西更有效率,我必须为解释器实现一些原语作为C#builtins。

到目前为止,我已将以下“原语”实现为C#内置函数:

  1. 过滤
  2. 地图(完整地图,而不仅仅是mapcar)
  3. foldr相似
  4. 但我怀疑,例如,我可能会使用map和foldr的组合来实现“过滤器”。

    我需要公开为“builtins”的最小原语集是什么,这样我可以在IEnumerable实例上实现任何其他功能,而不会产生过多的运行时或空间成本,而且不必引入变异?

3 个答案:

答案 0 :(得分:2)

System.Linq名称空间中已经存在所有函数。

  1. filter = Where
  2. map =选择
  3. fold / reduce = Aggregate(foldr = Reverse then Aggregate)
  4. 你会发现更多。例如

    SelectMany = map + map + flatten GroupBy =分区

    remq和朋友可以在过滤器方面完成。

    <强>更新

    与普通的Scheme定义不同,这些显然只占用1个列表参数。

答案 1 :(得分:2)

您不必严格要求map成为基元,因为您可以使用foldr来定义它。

示例(在Haskell中):

map f = foldr (\a b->f a:b) []

这实际上是mapcar而非map,但由于map不可用,因此很难在Haskell中表达完整的apply

更完整的示例(在Scheme中):

(define (mapcar f l)
  (foldr (lambda (x t) (cons (f x) t)) ‛() l))

(define (heads ls) (mapcar car ls))

(define (tails ls) (mapcar cdr ls))

(define (any-null? ls) (foldr or? ﹟f (mapcar null? ls)))

(define (map f . ls)
  (if (any-null? ls)
      ‛()
      (cons (apply f (heads ls)) (apply map f (tails ls)))))

如果您没有carcdr,还有其他方法可以定义它们,例如如果你有闭合&amp;您的语言中的变量:

(define (car a) (foldr (lambda (x y) x) ﹟f a))

(define (cdr a)
  (let ((prev ‛())
        (tmp #f))
    (foldr (lambda (h t) (set! tmp (cons h t)) (set! prev t) tmp)
           ‛()
           a)
    prev))

答案 2 :(得分:0)

我不太确定你的序列计算的功能是什么,但是连接操作(即展平嵌套序列)也可能非常有用。看看Haskell的列表理解是如何被人们去了解的原因。