我有一个类型类C.
class C a where
changeProperty :: a -> ??? -> a
C有两个(或更多)实例
data A = A AProperty X
data B = B BProperty Y
instance C A where
changeProperty (A _ x) ap = A ap x
instance C B where
changeProperty (B _ y) bp = B bp y
bp和ap是不同类型的。 AProperty仅与A兼容,BProperty仅与B兼容。是否可以为类型签名或其他允许方法changeProperty仅接受这些组合的解决方案制作一些?我能够想到的唯一选项是将方法完全分开(在本例中为changeAProperty和changeBProperty),或者要求我使AProperty和BProperty成为相同的类型,这允许无效的组合,如A与BProperty。理想情况下,我希望有一个属性类,其中AProperty和BProperty是实例,但我不知道如何做到这一点并避免无效组合。
编辑:此问题的上下文是用于构建MD模拟分子的脚本。 A,B等是原子之间的连接。例如,A将是一个键,包含AProperty中的这个键的参数和X中涉及的原子.B将是一个角度,BP将包含与该角度相关的参数,Y是原子等等。
答案 0 :(得分:4)
我喜欢其他解决方案的普遍性。但在这种特殊情况下,我想提出一个无类别的解决方案。
data Meta properties parameters = Meta properties parameters
changeProperty :: Meta props params -> props -> Meta props params
changeProperty (Meta props params) props' = Meta props' params
type A = Meta AProperty X
type B = Meta BProperty Y
这种事情是非常普遍的需要;另请参阅this question,了解实现此目的的记录访问器方式的简要概述,以及为减少与记录访问器相关的痛苦而建立的库。
答案 1 :(得分:3)
我估计你想要这个:
{-# LANGUAGE TypeFamilies #-}
class C a where
type CProperty a :: *
changeProperty :: a -> CProperty a -> a
data A = A AProperty X
data B = B BProperty Y
instance C A where
type CProperty A = AProperty
changeProperty (A _ x) ap = A ap x
instance C B where
type CProperty B = BProperty
changeProperty (B _ y) bp = B bp y
...或者,如果确实AProperty
仅适用于A
,则具有功能依赖性的MPTC解决方案:
{-# LANGUAGE FunctionalDependencies #-}
class C a ap | ap -> a, a -> ap where
changeProperty :: a -> ap -> a
data X = X
data Y = Y
data AProperty = AProperty
data BProperty = BProperty
data A = A AProperty X
data B = B BProperty Y
instance C A AProperty where
changeProperty (A _ x) ap = A ap x
instance C B BProperty where
changeProperty (B _ y) bp = B bp y
正如您已经注意到的,这也是在没有函数依赖性的情况下编译的,但是在实践中使用它通常很麻烦,因为对于所有编译器都知道,A
可以有任何其他属性和AProperty
可以应用于任何其他类型,因此您最终必须为类型检查器键入大量的explicits约束。
答案 2 :(得分:1)
正如Willem Van Onsem所提到的,可以使用多参数类型。
{-# LANGUAGE MultiParamTypeClasses #-}
class C a ap where
changeProperty :: a -> ap -> a
data X = X
data Y = Y
data AProperty = AProperty
data BProperty = BProperty
data A = A AProperty X
data B = B BProperty Y
instance C A AProperty where
changeProperty (A _ x) ap = A ap x
instance C B BProperty where
changeProperty (B _ y) bp = B bp y
至于它是否是我不知道的最佳解决方案。