剥离让进入Haskell [英] Stripping out let in Haskell

查看:77
本文介绍了剥离让进入Haskell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可能首先应该提到我对Haskell很陌生.将 let 表达式保留在Haskell中是否有特定的原因?

I should probably first mention that I'm pretty new to Haskell. Is there a particular reason to keep the let expression in Haskell?

我知道Haskell摆脱了 rec 关键字,该关键字与表示它是递归的 let 语句的Y-combinator部分相对应.他们为什么不完全放弃 let 语句?

I know that Haskell got rid of the rec keyword that corresponds to the Y-combinator portion of a let statement that indicates it's recursive. Why didn't they get rid of the let statement altogether?

如果这样做的话,声明在某种程度上似乎会更迭代.例如,类似:

If they did, statements will seem more iterative to some degree. For example, something like:

let y = 1+2
    z = 4+6
    in y+z

将是:

y = 1+2
z = 4+6
y+z

对于那些刚接触函数式编程的人来说,这更容易阅读和易于理解.我能想到的唯一原因就是这样:

Which is more readable and easier for someone new to functional programming to follow. The only reason I can think of to keep it around is something like this:

aaa = let y = 1+2
          z = 4+6
          in  y+z

在没有 let 的情况下会看起来像这样,我认为这最终是模棱两可的语法:

Which would look this this without the let, which I think ends up being ambiguous grammar:

aaa = 
  y = 1+2
  z = 4+6
  y+z

但是,如果Haskell不忽略空格,并且代码块/作用域类似于Python,它是否可以删除 let ?

But if Haskell didn't ignore whitespace, and code blocks/scope worked similar to Python, would it be able to remove the let?

是否有更强的理由让 let 保持联系?

Is there a stronger reason to keep around let?

很抱歉,如果这个问题看起来很愚蠢,我只是想了解更多关于它为何存在的信息.

Sorry if this question seems stupid, I'm just trying to understand more about why it's in there.

推荐答案

从语法上讲,您可以轻松地想象没有 let 的语言.立即,如果需要,我们可以仅依靠 where 在Haskell中生成此代码.除此之外,还有许多可能的语法.

Syntactically you can easily imagine a language without let. Immediately, we can produce this in Haskell by simply relying on where if we wanted. Beyond that are many possible syntaxes.

从语义上讲,您可能会认为let可以翻译成类似这样的内容

Semantically, you might think that let could translate away to something like this

let x = e in g      ==>    (\x -> g) e

,实际上,在运行时,这两个表达式是相同的(模态递归绑定,但是可以使用 fix 来实现).但是,传统上, let 具有特殊的键入语义(以及 where 和顶级名称定义...所有这些实际上都是 let的语法糖)).

and, indeed, at runtime these two expressions are identical (modulo recursive bindings, but those can be achieved with fix). Traditionally, however, let has special typing semantics (along with where and top-level name definitions... all of which being, effectively, syntax sugar for let).

尤其是在构成Haskell基础的Hindley-Milner类型系统中,有一个 let -泛化的概念.从直觉上讲,它涉及将功能升级到其最多态形式的情况.特别是,如果我们有一个函数出现在表达式中某个类型类似

In particular, in the Hindley-Milner type system which forms the foundation of Haskell there's a notion of let-generalization. Intuitively, it regards situations where we upgrade functions to their most polymorphic form. In particular, if we have a function appearing in an expression somewhere with a type like

a -> b -> c

这些变量 a b c 在该表达式中可能具有或没有含义.特别是,它们被假定为固定的但未知的类型.将其与类型进行比较

those variables, a, b, and c, may or may not already have meaning in that expression. In particular, they're assumed to be fixed yet unknown types. Compare that to the type

forall a b c. a -> b -> c

通过立即指出即使有类型变量 a b 和<该环境中提供了code> c ,这些这些参考是新鲜.

which includes the notion of polymorphism by stating, immediately, that even if there happen to be type variables a, b, and c available in the envionment, these references are fresh.

这是HM推理算法中非常重要的一步,因为它是生成的方式,使HM可以达到其更通用的类型.不幸的是,只要我们愿意,就不可能执行此步骤-必须在受控点完成.

This is an incredibly important step in the HM inference algorithm as it is how polymorphism is generated allowing HM to reach its more general types. Unfortunately, it's not possible to do this step whenever we please—it must be done at controlled points.

这就是 let 泛化的作用:它表示将类型 let 绑定到特定名称时,应该将类型泛化为多态类型.仅将它们作为参数传递给函数时,不会发生这种概括.

This is what let-generalization does: it says that types should be generalized to polymorphic types when they are let-bound to a particular name. Such generalization does not occur when they are merely passed into functions as arguments.

因此,最终,您需要一种"let"形式来运行HM推理算法.此外,尽管它们具有等效的运行时特性,但它不能只是函数应用程序的语法糖.

So, ultimately, you need a form of "let" in order to run the HM inference algorithm. Further, it cannot just be syntax sugar for function application despite them having equivalent runtime characteristics.

从语法上讲,这个"let"概念可以称为 let where 或通过顶级名称绑定的约定(所有三个名称都可以在Haskell中使用).只要它存在并且是生成绑定名称的主要方法,人们就会期望它具有多态性,那么它将具有正确的行为.

Syntactically, this "let" notion might be called let or where or by a convention of top-level name binding (all three are available in Haskell). So long as it exists and is a primary method for generating bound names where people expect polymorphism then it'll have the right behavior.

这篇关于剥离让进入Haskell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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