繁体   English   中英

Haskell名称声明规则

[英]Haskell name declaration rules

我正在自学Haskell,我遇到了两个“翻转”功能的实现,它为我提出了关于名称声明的问题。

这两个做同样的事情:

flip'' :: (a -> b -> c) -> b -> a -> c  
flip'' f y x = f x y  

flip' :: (a -> b -> c) -> (b -> a -> c)  
flip' f = g  
    where g x y = f y x  

第一个例子正如我所料。 在第二个例子中,我很困惑为什么当我们还没有声明x或y时我们被允许写gxy = fyx 我理解懒惰的评估意味着在需要它们之前都不会进行评估,但我希望编译器至少需要一个声明。

即使没有类型签名,它也会编译...这很好用:

flip' f = g  
    where g x y = f y x 

那么x和y只是完全无类型的变量吗? 或者还有其他事情发生了吗? 为什么我们能做到这一点?

where工作方式与声明一个全新的功能完全相同。 唯一的区别是函数存在于使用where的函数的局部范围内。 这意味着您在调用时提供的代码相当于:

flip' f -- Equivalent to flip' (\x y -> f x y) 
-- After we call it we have in our environment(scope) function f

g x y = f y x -- Here you call it and it is perfectly fine, because f is defined

类型怎么样? 编译器尝试根据它所拥有的信息推断出g的类型。 它具有的信息是g类型必须与f相同,除了参数的翻转顺序,它还注意到f只有两个参数。 所以类型推导算法一般说如果f :: a -> b -> cg :: b -> a -> c

我很困惑为什么在我们还没有声明x或y的时候我们被允许写gxy = fyx。

由于g,x和y出现在等号的左边,所以它们实际上是声明的。 where将介绍其所附代码的本地范围。 代码可以写成:

flip f = let g x y = f y x in g

在英语中:设g是一个带有两个参数x和y的函数....

第二个例子没有什么特别之处。 同样在第一个示例中,类型签名是可选的,因此以下行自行运行:

flip'' f y x = f x y

在Haskell中,您不必指定变量的类型,但Haskell实现可以为您推断它们。 您可以在ghci中使用:t flip''来检查推断的flip''类型是否是您所期望的。

那么你可以在Haskell中使用没有声明或没有类型的变量吗? 不可以。例如,您只能使用绑定在某处的变量,因为它们出现在等式中=符号的左侧。 并且每个变量都必须有一个类型,即使它是一个多态类型变量,如问题中的abc 只是程序员不必向Haskell实现声明类型,但Haskell实现可以根据变量的使用方式来计算类型。

请注意,这种“计算输出”业务仍然是静态类型 Haskell实现首先计算出所有变量的类型,然后编译或运行程序。 因此,如果存在类型错误,则在程序开始运行之前会收到错误消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM