[英]Constraints on a Haskell typeclass for the definition of a group
我想出了一个Group的类型类定义,但是我找到了一个实际上并不是一个组的反例类型。
这是类定义和一个实例,即组ℤ2:
class Group g where
iden :: g
op :: g -> g -> g
inv :: g -> g
data Z2T = Z0 | Z1
instance Group Z2T where
iden = Z0
Z0 `op` Z0 = Z0
Z0 `op` Z1 = Z1
Z1 `op` Z0 = Z1
Z1 `op` Z1 = Z0
inv Z0 = Z1
inv Z1 = Z0
但是, Group
那些类型签名是必要的,但是对于一个真正成为一个组的类型来说还不够,这里是我编译的反例:
data NotAGroup = N0 | N1
instance Group NotAGroup where
iden = N0
N0 `op` N0 = N0
N1 `op` N0 = N0
N0 `op` N1 = N0
N1 `op` N1 = N0
inv N0 = N0
inv N1 = N0
如何将类型的足够规则编码为Haskell中的Group
类型类中的Group
?
你是对的,可以写出违反集团法的Group
类型类的实例,因为实际上代码中没有任何内容实际说明它们。
对于Monad
类来说,这种情况也是如此,其中monadic法则不是以任何方式编写或强制执行的。 您可以编写一个非法的Monad
实例,因为您可以编写一个非法的Group
实例。
这实际上是你在Haskell中可以获得的最好的,至少不会过多地增加类型签名的复杂性。 事实上,要表达类型中的组定律,您可能需要一种完全依赖类型的语言,而Haskell则不然。
在这种情况下,法律通常写在评论中,可能表示为重写规则,程序员通常具有足够的纪律来尊重它们。
您无法执行此类法律,但您可以记录这些法律。 例如, Monoid
类记录了Monoid
任何实例应遵守的四个定律:
-- | The class of monoids (types with an associative binary operation that
-- has an identity). Instances should satisfy the following laws:
--
-- * @mappend mempty x = x@
--
-- * @mappend x mempty = x@
--
-- * @mappend x (mappend y z) = mappend (mappend x y) z@
--
-- * @mconcat = 'foldr' mappend mempty@
一个组只是一个具有额外逆操作的幺半群。 使您的Group
类成为Monoid
的子类; 那么你只需要记录你的逆操作必须遵守的附加法则。
class Monoid g => Group g where
ginverse :: g -> g
-- ginv must obey the following laws
-- x `gappend` (ginverse x) == gempty
-- (ginverse x) `gappend` x == gempty
-- g-prefixed synonym for mappend
gappend :: Group g => g -> g -> g
gappend = mappend
-- g-prefixed synonym for mempty
gempty :: Group g => g
gempty = mempty
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.