【问题标题】:Reusing a Lambda function in Haskell在 Haskell 中重用 Lambda 函数
【发布时间】:2011-11-19 16:50:42
【问题描述】:

我应该接受这个代码:

f x y z = x^3 - g (x + g (y - g z) + g (z^2))
 where g x = 2*x^2 + 10*x + 1

并在没有 where(或 let)的情况下重写它。

他们的意思是用 Lambda 函数 (\x ->...)

我正在尝试在 Haskell 上重用 Lambda 函数。有什么想法吗?

【问题讨论】:

  • f = flip flip ((1 +) . ap ((+) . (2 *) . (^ 2)) (10 *)) . (flip .) . ap ((.) . (.) . (.) . (-) . (^ 3)) (((ap id .) .) . flip flip (flip id . (^ 2)) . (liftM2 (liftM2 (+)) .) . (. ((ap id .) . (. flip id) . (.) . (-))) . (.) . (.) . (+)): f 被 lambdabot 弄得毫无意义

标签: haskell lambda-calculus


【解决方案1】:

正如 bravit 所暗示的,您可以通过以下方式使用 lambda 重写非递归 let

let x = A in B     ==>     (\x -> B) A 

其中x 是一个变量,AB 是表达式。

【讨论】:

  • 我觉得这个技巧很有趣的是,它实际上是 Javascript 中的一种标准做法,因为只有函数才能在其中引入范围块。
  • 我仍然不确定我是否理解如何能够重复使用它
  • @Asaf:可以在B中多次引用x。例如,以(\x -> x + x) 3 为例。这相当于3 + 3,除了你只需要写一次3
  • @Asaf 这里有一个提示:记住 lambda 的参数可能它们自己是函数。
【解决方案2】:

要重用某物,您可以将其作为某物的参数。

【讨论】:

    【解决方案3】:

    我认为意图是 bravit 所暗示的。
    smartypants 遵循法律的解决方法是将gcase 绑定;)

    【讨论】:

    • 另一个 smartypants 解决方案是将 g 设为顶级函数,因为它不会关闭来自 f 的任何内容 :)
    【解决方案4】:

    为了扩展 hammar 和 bravit 的提示,您的解决方案不仅需要一个 lambda,而且需要两个 - 其中一个看起来很像 g,而另一个看起来很像后半段f

    【讨论】:

      【解决方案5】:

      使用 lambda 演算 g(\x -> 2*x^2 + 10*x + 1)

      所以你需要用f x y z = x^3 - g (x + g (y - g z) + g (z^2))中的g替换

      $> echo "f x y z = x^3 - g (x + g (y - g z) + g (z^2))" | sed -r -e 's/g/(\\x -> 2*x^2 + 10*x + 1)/g'
      f x y z = x^3 - (\x -> 2*x^2 + 10*x + 1) (x + (\x -> 2*x^2 + 10*x + 1) (y - (\x -> 2*x^2 + 10*x + 1) z) + (\x -> 2*x^2 + 10*x + 1) (z^2))
      

      我只是在开玩笑,对不起。

      【讨论】:

      • 我相信他的导师不会对这个答案感到兴奋 ;)
      • 这正是我要给出的答案。据我所知,问题归结为“在这里,使用这个惯用代码并使其变得更糟,只是为了证明你知道 X”。如果老师想检查我是否知道 X,他们应该提出一个问题,X 实际上是有用/必要的。
      【解决方案6】:

      这个问题对我来说似乎有点奇怪和有趣。所以,我试图弄清楚什么是 lambda 演算,找到答案并想把它展示给 OP(实际上所有的提示都已经显示出来了,剧透警告)。

      首先,让我们尝试重新定义f

      λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2)))
      f ::
        (Integer -> Integer) -> Integer -> Integer -> Integer -> Integer
      

      所以,我们有函数,它获取函数和 3 个数字并返回答案。使用curring我们可以在这里添加g定义,比如f_new = f g

      λ> let f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1)
      f :: Integer -> Integer -> Integer -> Integer
      

      我们完成了。让我们检查一下:

      λ> f 0 0 0
      -13
      

      答案是正确的。

      UPD

      在这些例子中,let 只是在解释器中声明函数的一种方式,所以最终答案是:

      f :: Num a => a -> a -> a -> a
      f = (\g x y z -> x^3 - g(x + g(y - g z) + g(z^2))) (\x -> 2*x^2 + 10*x + 1)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-28
        • 1970-01-01
        相关资源
        最近更新 更多