实例签名:对方法的约束

使用InstanceSignatures,我可以为实例 decl 中的方法签名。

实例声明中的类型签名必须比类声明中的类型签名更多(或相同),使用实例类型实例化。

我可以从这个答案中看到sig 的类型部分不能更具体;但是为什么不能添加额外的约束呢?毕竟,您可以对实例 decl 施加约束,这将使实例比“使用实例类型实例化的类声明”更具体。

Addit:(响应前几条评论。)为了解释“您可以对实例 decl 进行约束……更具体的OVERLAPPABLE实例”:这里的实例头声称它提供addNat了所有类型a, b, c。但它没有:它只提供 if ais of the form SNat a'cis of the formSNat c'等。我在问为什么我不能在方法级别同样限制类型?

例如[改编自 Hughes 1999](更现实地说,这可能是 BST/玫瑰树等):

data AscList a = AscList [a]                          -- ascending list

instance Functor AscList  where                       -- constructor class
  fmap f (AscList xs) = AscList $ sort $ fmap f xs
  -- :: Ord b => (a -> b) -> AscList a -> AscList b   -- inferred

没有实例签名 GHC 会抱怨no instance for (Ord b)。带有签名的 GHC 抱怨来自is more polymorphic than给定类的实例化 sig 。

这个(优秀的)答案解释了实例字典中的机制。我可以看到字典中该方法的条目具有从类 decl 中方法(如果有)的约束数设置的类型。没有空间为该方法放置额外的字典/参数。

这似乎只是实施没有预见到需要。是否有更深层次/更基于理论的反对理由?

(顺便说一句,我对 Hughes 的方法并不那么信服:那会同时需要Ord a => WFT(AscList a)Ord b => WFT(AscList b)。但是没有必要要求传入(AscList a)是上升的。其他构造函数类AscList可能在Ord任何地方都不需要约束。)

回答

如果您允许向不在类方法中的实例方法添加约束,则使用类型类的多态函数在您专门化它时可能不再进行类型检查。

例如,考虑AscList上面的实例,以及以下用法Functor

data T f = T (f (IO ()))  -- f applied to a non-Ord

example :: Functor f => T f -> T f
example (T t) = T (fmap (x -> x >> print 33) t)
  1. 类型example表示您可以f使用任何函子实例化,例如f = AscList.
  2. 但这毫无意义,因为它会尝试对AscList (IO ()).

当我们example在这里专门研究时,唯一能判断出问题的方法是阅读它的定义,找出 offmap的用法是否仍然有效,这与模块化背道而驰。类型签名中的类型类约束不会也不应该记录如何使用它们的方法。相反,这意味着实例不能向它们的方法实现添加约束。


以上是实例签名:对方法的约束的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>