HasResolution类型类

问题描述 投票:7回答:1

我只是抬头查看了HasResolution typeclass,它有一个方法,resolution声明如下:

class HasResolution a where
   ...
   resolution :: p a -> Integer

我不明白上述声明中的p。它来自哪里,它意味着什么?

haskell
1个回答
13
投票

这只是一个代理人。

如果你有

class HasResolution a where
  resolution :: Integer

你会被大吼大叫,因为当你调用HasResolution时,编译器无法推断出你需要哪个resolution实例。具体来说,resolution :: HasResolution a => Integera出现在左边但不在右边,所以你永远不能推断a

所以,一个解决方案是

class HasResolution a where
  resolution :: a -> Integer

resolution的文件会说它不是要检查a;它只是让编译器找出要选择的实例。你将它用作resolution (undefined :: a)。然后,另一个解决方案出现

data Proxy a = Proxy

class HasResolution a where
  resolution :: Proxy a -> Integer

Proxy没有向resolution提供任何信息;它只存在于编译器推断a是什么。它比原来更好resolution真的无法检查它的论点,所以Integer真的与类型有关,而不是resolution的论证。它的情况稍差(或更好,取决于你问的是谁),因为使用的是更冗长的resolution (Proxy :: Proxy a)(你不能只使用undefined因为实现可能在Proxy上模式匹配)。

这演变成了

class HasResolution a where
  resolution :: p a -> Integer

这意味着你没有被限制在Proxy,这意味着如果你有例如位于范围内的[a],你可以将它传递给resolution而不会产生大量的冗长,同时保持与刚刚使用Proxy的代码的兼容性。同样,resolution的第一个参数仅供编译器使用。它对实际实现没有任何意义。您只需使用它来选择所需的HasResolution实例。

Proxy最终变得如此普遍,以至于GHC.Exts获得了新成员:Proxy#Proxy#没有运行时表示,因此它不会导致性能损失,这与Proxy(或上述多态p技巧)不同。然而,Proxy#的事实是它的类型是forall k. k -> TYPE (TupleRep '[])。如果没有像所有其他“乖巧”的类型一样生活在*,它就不能参与多态的p技巧。

class HasResolution a where
  resolution :: Proxy# a -> Integer

第一个解决方案相当过时,尽管有时会看到示例。第二个和第三个相当普遍,第四个被最近的解决方案很快取代,这是为了启用-XTypeApplications -XAllowAmbiguousTypes而且只是

class HasResolution a where
  resolution :: Integer

再次。 -XAllowAmbiguousTypes避开错误,-XTypeApplications允许你在呼叫站点指定aresolution @a。这不能用在需要一定程度向后兼容的代码中,但是在需要新GHC的库中你会看到更多,并且可以承受不具备兼容性。

© www.soinside.com 2019 - 2024. All rights reserved.