Haskell rec关键字如何工作? [英] How does the Haskell rec keyword work?

查看:128
本文介绍了Haskell rec关键字如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在箭头符号中,可以使用rec关键字来编写递归定义。例如:

  rec 
name< - function - <输入
input< - otherFunction - <名称

如何评估?它似乎会进入一个无限循环或什么东西。我知道它评估到循环箭头组合器,但我不明白它是如何工作的。



编辑:该权力示例是非常有用的。尽管如此,你会如何写这个符号?我假设你需要使用rec。

解决方案

由于haskells懒惰,这一点魔法有效。正如您可能知道的那样,Haskell在需要时评估一个值,而不是在定义时评估。因此,如果你不需要直接输入的价值,或者稍后输入价值,那么这就很有效。

rec 是使用 ArrowLoop 循环函数实现。它定义如下:

  class Arrow a => ArrowLoop a其中
loop :: a(b,d)(c,d) - > abc

实例ArrowLoop( - >)其中
loop fb = let(c,d)= f(b,d)in c

您可以看到:输出仅作为输入反馈。它只会计算一次,因为Haskell只会在需要时评估 d



下面是一个实际的例子如何直接使用循环组合子。这个函数计算它的参数的所有权力:

  powers = loop $ \(x,l) - > (l,x:map(* x)l)



<你也可以这样写: powers x = fix $(x :)。map(* x)


那么,权力的无限列表在 l 参数中。评估如下:

pre $ power $ loop $ \(x,l) - > (l,x:map(* x)l)==> (c,d)=(\(x,l) - >(l,x:map(* x)l))(b,d)在c ==>
幂b = let(c,d)=(d,b:map(* b)d)in d ==> - 现在我们用2作为参数
幂2 = let(c,d)=(d,2:map(* 2)d)in d ==> (c,(2:d))=(d,2:map(* 2)d)in c ==> (c,(2:4:d))=((2:d),2:映射(* 2)(2:d)) $()()=((2:4:d),2:map(* 2)(2:4:d))in ==> - 等等


In arrow do notation, you can use the rec keyword to write recursive definitions. So for example:

rec
    name <- function -< input
    input <- otherFunction -< name

How can this ever evaluate? It seems like it would just go into an infinite loop or something. I know it evaluates to the loop arrow combinator, but I don't understand how that works either.

EDIT: that powers example is really helpful. How would you write that with do notation, though? I assume you would need to use rec.

解决方案

This bit of magic works due to haskells laziness. As you might know, Haskell evaluates a value when needed, not when defined. Thus, this works if you don't need the value fed in directly, or maybe later.

rec is implemented using the loop function of ArrowLoop. It is defined as followed:

class Arrow a => ArrowLoop a where
        loop :: a (b,d) (c,d) -> a b c

instance ArrowLoop (->) where
        loop f b = let (c,d) = f (b,d) in c

You can see: The output is just fed back as the input. It will be calculated just once, because Haskell will only evaluate d when it's needed.

Here's an actual example of how to use the loop combinator directly. This function calculates all the powers of it's argument:

powers = loop $ \(x,l) -> (l,x:map(*x)l)

(You could also write it like this instead: powers x = fix $ (x :) . map (*x))

How does it works? Well, the infinite list of powers is in the l argument. The evaluation looks like this:

powers = loop $ \(x,l) -> (l,x:map(*x)l) ==>
powers b = let (c,d) = (\(x,l) -> (l,x:map(*x)l)) (b,d) in c ==>
powers b = let (c,d) = (d,b:map(*b)d) in d ==> -- Now  we apply 2 as an argument
powers 2 = let (c,d) = (d,2:map(*2)d) in d ==>
         = let (c,(2:d)) = (d,2:map(*2)d) in c ==>
         = let (c,(2:4:d)) = ((2:d),2:map(*2)(2:d)) in c ==>
         = let (c,(2:4:8:d)) = ((2:4:d),2:map(*2)(2:4:d)) in  ==> -- and so on

这篇关于Haskell rec关键字如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆