Haskell:在类型类之间转换

时间:2016-03-16 02:12:43

标签: haskell

对于这些数据:

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位于外部库中。

2 个答案:

答案 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扩展名。