[英]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 -> c
则g :: 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中使用没有声明或没有类型的变量吗? 不可以。例如,您只能使用绑定在某处的变量,因为它们出现在等式中=
符号的左侧。 并且每个变量都必须有一个类型,即使它是一个多态类型变量,如问题中的a
, b
和c
。 只是程序员不必向Haskell实现声明类型,但Haskell实现可以根据变量的使用方式来计算类型。
请注意,这种“计算输出”业务仍然是静态类型 。 Haskell实现首先计算出所有变量的类型,然后编译或运行程序。 因此,如果存在类型错误,则在程序开始运行之前会收到错误消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.