以下功能不会检查。
test1 :: forall x. (Show x => x) -> String
test1 = show
这是因为最后->
无法访问约束。 (这可能不是正确的术语,但希望它有意义。)我一直试图找到类似于上述类型签名的用法,其中最终->
没有有权访问约束。但我无法想到任何例子。
所以我的问题是:是否有一种情况,我们在类型签名中设置约束是否有用,最终->
无法访问?
请注意,test1
与下面的排名2功能不同。
test2 :: (forall x. Show x => x) -> String
test2 = show
我对第一种情况感兴趣,而不是这种情况。 RankNTypes
在标题中的原因是因为需要启用该扩展程序才能为test1
创建类型签名。
答案 0 :(得分:3)
将类约束视为推断的函数参数是有用的,因为它们对GHC Core中的函数和函数应用程序感到厌恶。
让我们去讨论这个类型:
newtype ShowDict a = ShowDict (a -> String)
test1 :: forall x. (ShowDict x -> x) -> String
或更简单:
test1 :: forall x. ((x -> String) -> x) -> String
这种类型并不是很有用。通过参数化,它的实现必须是返回一些字符串的常量函数。
使用原始的非desugared类型,我们甚至无法对(Show x => x)
参数执行任何操作,因为我们的普遍量化{{{}没有任何Show
字典。{ 1}}。
所以我的问题是:是否存在我们有用的情况 最终的类型签名中的约束 - >没有访问权限 到?
这有点含糊不清,但我可以论证以下内容:形式x
的函数参数类型(可能在外部范围内量化(c x => t)
)在Haskell中永远不会有意义。
类的一致性意味着每种类型最多只有一个实例,因此x
上的抽象不会产生任何计算差异。如果没有c x
,那么(desugared)函数永远不会被应用,但是如果我们已经知道有一个唯一的c x
,那么为什么要依赖它?
答案 1 :(得分:2)
并不是说您无法访问它,而是对类型实例化的控制被颠倒了:使用rank-2类型,您可以更改谁选择类型
在您的示例中,test2
函数可以选择其参数的类型。所以,例如,这编译:
test2 :: (forall x. Show x => x) -> String
test2 a = show (a :: Char)
这是因为参数a
对于作为Show
实例的所有类型必须完全符合。因此,我们永远无法调用test2
,因为我们永远无法提供可以采用Show
实例的所有可能类型的值。
请注意我们写过
test2 :: Show x => x -> String
test2 a = ...
test2
的来电者可以选择a
的类型,test2
是Show
的所有实例必须有效的example :: (forall x. Show x => x -> Int) -> Int
example f = 10 * f True
让我们看一个稍微有用的例子:
example
我们再次看到,我们(即x
)可以选择Bool
类型变量所代表的类型(实例化该类型变量为某种类型)。在这里,我们选择ghci> example (length . show)
40
类型。以下是您可以调用此函数的方法:
example2 :: (forall x. [x] -> [x]) -> [Int]
example2 f = f [1, 2, 3]
这是另一个例子:
ghci> example2 reverse
[3,2,1]
我们可以在列表上给它任何函数,只要该函数不关心该列表中的实际值。由于函数不知道这些值的类型,因此无法以任何方式检查它们(此属性称为parametricity)。
所以,我们可以这样做:
ghci> let addOne :: Int -> Int
|> addOne a = a + 1
|>
ghci> example2 (map addOne)
<interactive>:33:15:
Couldn't match type ‘x’ with ‘Int’
‘x’ is a rigid type variable bound by
a type expected by the context: [x] -> [x] at <interactive>:33:1
Expected type: x -> x
Actual type: Int -> Int
In the first argument of ‘map’, namely ‘addOne’
In the first argument of ‘example2’, namely ‘(map addOne)’
......但不是这样的:
lens
就实际效用而言,rank-n类型广泛用于(例如)Functor
库。这允许您表达函数使用Functor
实例而不知道它是哪个特定fmap
实例(即,它只使用Functor
)的想法。因此,当你传递它时,你可以给它任何你想要的 $allowed_extensions = array("gif", "jpeg", "jpg", "png");
$files = glob('files/*');
natcasesort($files);
foreach($files as $file){
if(!in_array(end(explode(".",$file)),$allowed_extensions)){
$image = "http://fitter.henry-griffitts.com/fitter/images/pdf.png";
}else{
$image = $file;
}
echo '<div class="one_half"><img src="' . $image . '" class="images" /></br><h2>' .basename($file). '</h2><a class="download" href="http://fitter.henry-griffitts.com/fitter/download.php?file='.base64_encode($file).'"></a></div>';
}
?>
个实例。