Haskell 类型族:如何为成对数据类型族实例化Bifunctor?
我试图理解如何使用数据类型族隐藏构造函数。给出的一个简单示例是一个具有从普通对和转换为普通对等操作的对。bifunctor的实例未编译;错误消息是Haskell 类型族:如何为成对数据类型族实例化Bifunctor?,haskell,type-families,Haskell,Type Families,我试图理解如何使用数据类型族隐藏构造函数。给出的一个简单示例是一个具有从普通对和转换为普通对等操作的对。bifunctor的实例未编译;错误消息是 src/TypeFamilyTest.hs:66:21: Bifunctor的第一个参数应该是kind*->*->*, 但是对AB具有种类ghc-prim-0.4.0.0:ghc.prim.Constraint 在Bifunctor(对a和对b) 尝试Bifunctor对,其中…我收到另一条错误消息,列出了相同的GHC.Prim.Constraint
src/TypeFamilyTest.hs:66:21
:
Bifunctor
的第一个参数应该是kind*->*->*
,
但是对AB
具有种类ghc-prim-0.4.0.0:ghc.prim.Constraint
在Bifunctor(对a和对b)
尝试Bifunctor对,其中…
我收到另一条错误消息,列出了相同的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)
类型错误告诉您一切<代码>对不是数据类型的名称。它是一个类的名称<代码>对a b::约束so
对::*->*->约束
Bifunctor
只能由类型为*->*->*
的数据类型实例化
我猜你的意思可能是这样的:
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
作为关联类型。我怀疑这可能是一个-您真正想要实现的目标是什么?类型错误告诉您一切<代码>对不是数据类型的名称。它是一个类的名称<代码>对a b::约束so对::*->*->约束
Bifunctor
只能由类型为*->*->*
的数据类型实例化
我猜你的意思可能是这样的:
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
作为关联类型。我怀疑这可能是一个-您真正想要实现的目标是什么?数据族不是关于隐藏构造函数的。它们的构造函数可以以与普通数据类型相同的方式显示或隐藏。数据族是关于非参数数据类型的——在决定其构造函数的外观之前检查其类型参数的类型。类型类不是面向对象意义上的类。它不封装数据及其操作。Haskell类的最接近OOP的概念是类似Java的接口
,甚至这种对应关系也是松散的。您可以定义一个类型newtype Vec2'a b=Vec2'(Vec2 a b)
,并且可以根据自己的内容创建该类型的类型类实例。但是,此类型不是Bifunctor
。bimap
的类型为(a-b对,a-b对)=>(a->a')->(b->b')->Vec2'a-b->Vec2'a'b'
谢谢您的澄清。我不明白你为什么要引进一种新类型。Vec2和Vec2'有什么区别?两者都有两个参数?附加包装的好处是什么?数据族并不是隐藏构造函数。它们的构造函数可以以与普通数据类型相同的方式显示或隐藏。数据族是关于非参数数据类型的——在决定其构造函数的外观之前检查其类型参数的类型。类型类不是面向对象意义上的类。它不封装数据及其操作。Haskell类的最接近OOP的概念是类似Java的接口
,甚至这种对应关系也是松散的。您可以定义一个类型newtype Vec2'a b=Vec2'(Vec2 a b)
,并且可以根据自己的内容创建该类型的类型类实例。但是,此类型不是Bifunctor
。bimap
的类型为(a-b对,a-b对)=>(a->a')->(b->b')->Vec2'a-b->Vec2'a'b'
谢谢您的澄清。我不明白你为什么要引进一种新类型。Vec2和Vec2'有什么区别?两者都有两个参数?附加包装器的好处是什么?看起来OP试图模拟面向对象编程,而Pairs
是一种封装Vec2
的类型。他们的尝试在语法上是正确的,这是巧合。我很感激这些有用的答案。我试图在一个程序中减少混乱,我觉得我有太多的类,并开始试验相关的类型。我现在更好地理解了,哪些关联类型是有用的,并将按照建议的思路使用解决方案。-非常感谢。看起来OP试图模拟面向对象编程,Pairs
是一种封装Vec2
的类型。他们的尝试在语法上是正确的,这是巧合。我很感激这些有用的答案。我试图在一个程序中减少混乱,我觉得我有太多的类,并开始试验相关的类型。我现在更好地理解了,哪些关联类型是有用的,并将按照建议的思路使用解决方案。-非常感谢。