理解 Haskell 的 RankNTypes [英] Understanding Haskell's RankNTypes

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

问题描述

在使用 GHC 扩展的过程中,我遇到了 RankNTypes 在 Haskell 学院,其中有以下示例:

While working my way through GHC extensions, I came across RankNTypes at the School of Haskell, which had the following example:

main = print $ rankN (+1)

rankN :: (forall n. Num n => n -> n) -> (Int, Double)
rankN f = (f 1, f 1.0)

这篇文章为 rankN 提供了另一种类型:

The article offered an alternative type for rankN:

rankN :: forall n. Num n => (n -> n) -> (Int, Double) 

区别的解释是

后一个签名需要一个从 n 到 n 的函数,用于某些 Num n;前一个签名要求每个 Num n 都有一个从 n 到 n 的函数.

The latter signature requires a function from n to n for some Num n; the former signature requires a function from n to n for every Num n.

我可以理解,前一种类型需要签名才能在括号中或更一般的内容.我不明白后一个签名只需要一个函数 n -> 的解释.n 表示某些 Num n".有人可以详细说明和澄清吗?你如何阅读"?这个以前的签名让这听起来像什么意思?后一个签名是否与简单的 Num n => 相同?(n -> n) ->(Int, Double) 不需要forall?

I can understand that the former type requires a signature to be what's in the parentheses or more general. I do not understand the explanation that the latter signature simply requires a function n -> n for "some Num n". Can someone elaborate and clarify? How do you "read" this former signature so that it sounds like what it means? Is the latter signature the same as simply Num n => (n -> n) -> (Int, Double) without the need for forall?

推荐答案

在正常情况下 (forall n.Num n => (n -> n) -> (Int, Double)),我们选择一个 n first 然后提供一个函数.所以我们可以传入一个 Int -> 类型的函数.Int, 双 ->Double, Rational ->理性等.

In the normal case (forall n. Num n => (n -> n) -> (Int, Double)), we choose an n first and then provide a function. So we could pass in a function of type Int -> Int, Double -> Double, Rational -> Rational and so on.

在 Rank 2 的情况下 ((forall n. Num n => n -> n) -> (Int, Double)) 我们必须提供函数 before 我们知道 n.这意味着该函数必须适用于any n;我为上一个示例列出的所有示例都不起作用.

In the Rank 2 case ((forall n. Num n => n -> n) -> (Int, Double)) we have to provide the function before we know n. This means that the function has to work for any n; none of the examples I listed for the previous example would work.

我们在给出的示例代码中需要这个,因为传入的函数 f 应用于两种不同的类型:IntDouble>.所以它必须对他们两个都有效.

We need this for the example code given because the function f that's passed in is applied to two different types: an Int and a Double. So it has to work for both of them.

第一种情况是正常的,因为默认情况下类型变量就是这样工作的.如果您根本没有 forall,那么您的类型签名就相当于在一开始就拥有它.(这称为前缀形式.)所以 Num n =>(n -> n) ->(Int, Double)forall n 隐含相同.数 n =>(n -> n) ->(Int, Double).

The first case is normal because that's how type variables work by default. If you don't have a forall at all, your type signature is equivalent to having it at the very beginning. (This is called prenex form.) So Num n => (n -> n) -> (Int, Double) is implicitly the same as forall n. Num n => (n -> n) -> (Int, Double).

适用于any n 的函数类型是什么?这正是 forall n.数 n =>n ->n.

What's the type of a function that works for any n? It's exactly forall n. Num n => n -> n.

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

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