haskell - 为什么关联类型同义词不暗示约束
问题描述
为什么在签名中使用关联类型同义词不暗示相应的约束?
例如,为什么以下内容不能编译:
{-# LANGUAGE TypeApplications, ScopedTypeVariables, TypeFamilies, AllowAmbiguousTypes #-}
class MyClass a where
type AssociatedType a
bar :: Int
foo :: forall a. AssociatedType a -> Int
foo _ = bar @a
ghc 8.6.5 给出以下错误:
error:
* No instance for (MyClass a) arising from a use of `bar'
Possible fix:
add (MyClass a) to the context of
the type signature for:
foo :: forall a. AssociatedType a -> Int
* In the expression: bar @a
In an equation for `foo': foo _ = bar @a
|
8 | foo _ = bar @a
| ^^^^^^
GHC 文档似乎没有提到这方面。
解决方案
如果它暗示了约束,那么任何以任何方式使用关联值的值的人都需要在范围内具有约束。例如,
sort :: Ord a => [a] -> [a]
显然一无所知MyClass
,但应该可以sort :: [AssociatedType a] -> [AssociatedType a]
在Ord (AssociatedType a)
调用范围内使用它。
要获得您似乎正在寻找的行为,您需要一个包装的约束而不是关联的类型。这不能用 来完成-XTypeFamilies
,但可以用 来完成-XGADTs
:
{-# LANGUAGE GADTs #-}
class MyClass a where
bar :: Int
data MyClassWitness a where
MyClassWitness :: MyClass a => MyClassWitness a
foo :: ∀ a. MyClassWitness a -> Int
foo MyClassWitness = bar @a
constraints
您也可以使用库中的包装器,而不是自卷包装器:
import Data.Constraint
foo :: ∀ a . Dict (MyClass a) -> Int
foo Dict = bar @a
在这两种情况下,重要的是您实际上在 GADT 构造函数上进行模式匹配,因为只有这样才能真正将约束带入范围。这不起作用:
foo :: ∀ a . Dict (MyClass a) -> Int
foo _ = bar @a
推荐阅读
- kubernetes - 如何将 K8s 服务同步到 K8s 外的 Consul Cluster?
- perl - 如何使用 perl 删除目录及其内容?
- ruby-on-rails - Rails 表单输入不保存,提交后变为空白
- java - JFrame actionlistener 在相同/链接的 JPanel actionlistener 之前激活
- excel - 选择单元格的通用分组(非静态)
- c++ - 如何从 cstdlib 修复 stdlib.h 的 include_next?
- google-cloud-platform - Issue to create domain mapping
- azure - AICS Test Report for Android device
- django - Export a specific data in an app in the django admin to a pdf
- javascript - 使用 JavaScript 动态显示/隐藏列不起作用