【发布时间】:2016-04-15 08:19:18
【问题描述】:
我试图了解如何使用数据类型族来隐藏构造函数。给出的简单示例是具有从普通对转换为普通对等操作的对。 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)
【问题讨论】:
-
数据族不是隐藏构造函数。它们的构造函数可以以与普通数据类型相同的方式可见或隐藏。数据族是关于非参数数据类型的——类型在决定它们的构造函数是什么样子之前检查它们的类型参数。
-
类型类不是面向对象意义上的类。它不封装数据和对其进行的操作。
-
Haskell
class的最接近 OOP 概念是类似于 Java 的interface,甚至这种对应关系也是松散的。 -
你可以定义一个类型
newtype Vec2' a b = Vec2' (Vec2 a b),你可以为这个类型创建类型类的实例来满足你的需求。但是,这种类型不是Bifunctor。bimap的类型将是(Pairs a b, Pairs a' b') => (a -> a') -> (b -> b') -> Vec2' a b -> Vec2' a' b' -
感谢您的澄清。我不明白你为什么要引入一个新类型。 Vec2 和 Vec2' 有什么区别?都有两个参数?额外的包装器有什么好处?
标签: haskell type-families