2016-04-15 36 views
0

我尝试了解如何使用数据类型族来隐藏构造函数。给出的微不足道的例子是一对具有从普通对转换成普通对的操作等)。 bifunctor的实例不能编译;该错误信息是类型族:如何为一对数据类型族实例化Bifunctor?

src/TypeFamilyTest.hs:66:21: 的Bifunctor的第一个参数应该有一种* -> * -> *, 但Pairs a b有种ghc-prim-0.4.0.0:GHC.Prim.Constraint

在实例声明Bifunctor (Pairs a b)

试图Bifunctor Pair where ...我再弄错误消息列表相同GHC.Prim.Constraint。该实例的正确参数是什么?上下文将如何传递?

class Pairs a b where 
    data Vec2 a b 

    mkPair :: (a,b) -> Vec2 a b -- (FirstF a, SecondF a) -> a 
    splitPair :: Vec2 a b -> (a,b) 
    fstP :: Vec2 a b -> a 
    sndP :: Vec2 a b -> b 
    fstP = fst . splitPair 
    sndP = snd . splitPair 

instance () => Bifunctor (Pairs a b) where 
    bimap opv oph vh = mkPair (opv . fstP $ vh, oph . sndP $ vh) 
+3

数据家族并不是隐藏构造函数。它们的构造函数可以以普通数据类型的相同方式显示或隐藏。数据族关于非参数数据类型 - 在决定其构造函数的外观之前检查其类型参数的类型。 –

+1

类型类不是面向对象意义上的类。它不封装数据和操作它的操作。 – chepner

+0

Haskell'class'最接近OOP的概念是类似Java的'interface',即使这种对应也是松散的。 – chi

回答

2

类型错误告诉你一切。 Pair不是数据类型的名称。这是一个班的名字。 Pair a b :: Constraint so Pair :: * -> * -> ConstraintBifunctor只能通过种类* -> * -> *的数据类型实例化。

我猜你的意思是不是这样的事情:

newtype Pair a b = Vec2 { splitPair :: (a, b) } 

fstP :: Pair a b -> a 
fstP = fst . splitPair 

sndP :: Pair a b -> b 
sndP = snd . splitPair 

instance Bifunctor Pair where 
    bimap f g (Vec2 (x, y)) = Vec2 (f x, g y) 

我不明白为什么你原先作出Vec2相应的类型。我怀疑这可能是一个XY problem - 你真的想达到什么目的?

+2

看起来OP正试图模拟面向对象的编程,'Pairs'是封装了'Vec2'的类型。这是巧合的,他们的尝试在语法上是正确的。 – chepner

+0

我欣赏有用的答案。我试图减少一个程序中的混乱,我觉得我有太多的类,并开始与相关类型的实验。我现在了解得更清楚,哪些关联类型对于建议的线路有用并将使用解决方案。 - 谢谢! – user855443