对于这些数据:
data A = A
data B = B
class C1 a where repr :: a -> String
instance C1 A where repr _ = "A"
instance C1 B where repr _ = "B"
class C2 a
instance C2 A
有没有办法用这种类型实现功能?
conv :: (C1 a, C2 b) => a -> Maybe b
它应该返回Just . id
作为C2
实例类型的参数,而Nothing
适用于任何其他类型。
repr
是单射的。我可以更改类C2
,但类C1
位于外部库中。
答案 0 :(得分:6)
不,这是不可能的。开放世界的假设表明,没有办法(在编译时或在运行时)显示给定类型不给定类的实例。
答案 1 :(得分:2)
为什么你需要C2
类型课?你可以这样做:
conv :: C1 a => a -> Maybe a
conv a = case repr a of
"A" -> Just a
_ -> Nothing
这可以假设repr
函数是injective。
修改:以下是如何按照您希望的方式实施conv
功能的方法:
{-# LANGUAGE TypeFamilies #-}
conv :: (C1 a, C2 b, a ~ b) => a -> Maybe b
conv a = case repr a of
"A" -> Just a
_ -> Nothing
请注意,等式约束a ~ b
是必需的。它告诉编译器类型a
和类型b
必须是同一类型。要使用等式约束,我们需要启用TypeFamilies
扩展名。