如何复用带函数依赖的类型类实现GetType类型级函数?
错误信息翻译
关联类型声明的右侧提到了超出作用域的变量‘a’
所有此类变量必须在左侧绑定
问题分析
你写的CanGetType类存在两个核心问题:
- 类参数
b完全多余——MyClass已经通过函数依赖name -> result保证了每个name对应唯一的result,不需要额外把结果类型作为类参数声明。 - 关联类型的定义不符合规则:类中声明的是
GetType a,但实例里的GetType name = result没有正确对应类参数的绑定逻辑,导致GHC判定变量作用域异常。
正确实现方案
方案一:使用开放类型家族(推荐)
不需要额外定义辅助类,直接通过类型家族结合MyClass的约束实现类型级函数:
{-# LANGUAGE TypeFamilies, FunctionalDependencies, ConstraintKinds #-} import GHC.TypeLits (KnownSymbol) class (KnownSymbol name) => MyClass name result | name -> result instance MyClass "something" Int -- 定义类型级函数GetType type family GetType name :: Type -- 利用MyClass的约束推导结果类型 type instance GetType name = result where constraint MyClass name result
方案二:调整辅助类写法
如果更倾向于用类实现,可以去掉多余参数,让辅助类直接复用MyClass的约束:
{-# LANGUAGE TypeFamilies, FunctionalDependencies, FlexibleInstances #-} import GHC.TypeLits (KnownSymbol) class (KnownSymbol name) => MyClass name result | name -> result instance MyClass "something" Int -- 辅助类仅保留输入类型参数 class KnownSymbol a => CanGetType a where type GetType a :: Type -- 复用MyClass实例实现类型推导 instance MyClass name result => CanGetType name where type GetType name = result
验证示例
通过类型签名可以验证效果:
test :: GetType "something" test = 42 -- 类型为Int,编译通过
内容的提问来源于stack exchange,提问作者Tsvetan Ovedenski
相关产品推荐
相关产品推荐

