1

我正在编写一个程序来表示有限群和对其元素的简单操作。我编写了我需要的大部分功能,例如逆元素、生成器、检查子集是否是子组等。

不幸的是,我所有的功能都需要标识元素、集合和操作。我想定义类的适当实例并使用它而不是这个三重奏。我的问题从这里开始,我不太清楚该怎么做,我在互联网上可以找到的所有内容仅包含定义示例,没有使用示例。

最终我想与组合作Sn,到目前为止,我已经在 ( Zn +) 上测试了我的代码。

我写了这个:

data Z2 = Elm Int deriving (Show, Eq)
z2 :: Int -> Z2
z2 a = Elm (a `mod` 2)

class FiniteGroup a where
    identity :: a
    op :: a -> a -> a -- operation
    set :: [a]

instance FiniteGroup Z2 where
    identity = (Elm 0)
    op (Elm x) (Elm y) = z2 (x+y)
    set = [(Elm 0), (Elm 1)]

它适用于 function op,例如:

*Main> (Elm 1) `op` (Elm 0)
Elm 1

不幸的是,我不能使用identityand set。我该如何使用它?

我也不知道如何重构现有函数以使用我的类型类。

例如我有这个:

cyclicGenerators :: (Eq a) => a -> [a] -> (a -> a -> a) -> [a]

它工作正常,但我想要这样的东西:

cyclicGenerators :: (Eq a) => FiniteGroup a -> [a]
4

1 回答 1

2

无法使用身份和设置,如何使用?

您必须在明确定义的上下文中使用它们a。例如提供显式类型注释

set :: [Z2]
identity :: Z2

将它们传递给一些需要 a 的函数Z2也可以。只要编译器能弄清楚你在说哪个有限群,你就可以了。否则,您将收到“模棱两可...”错误。

如何替换函数中的签名以及如何在我已经定义的函数中使用身份和设置。

试试例如

cyclicGenerators :: (Eq a, FiniteGroup a) => [a]
cyclicGenerators = filter isGenerator set
  where isGenerator x = ...  -- a Boolean telling whether it's a generator

上面的编译器“知道”set指的是有限组a,因为我们必须返回一个[a]并且filter不改变输入列表的类型,因此也set必须是类型[a]。这里类型推断在传播类型方面非常有效,因此可以选择正确的有限群实例。


编辑:OP提出了代码

cyclicGenerators :: (FiniteGroup a) => [a]
cyclicGenerators = filter isGenerator set
        where isGenerator = (\x -> groupOrder set == elemOrder x)

这会触发歧义错误。事实上,最后一个set并不强制属于同一个组——将另一个组的组顺序与 的顺序进行比较是有意义的x。例如groupOrder (set :: [Z5]) == elemOrder (identity :: [Z2])会键入检查,因为两者都是整数。

所以我们需要声明它的类型set[a]. 简单的 Haskell 方式是

 where isGenerator = (\x -> groupOrder (set `asTypeOf` [x]) == elemOrder x)

whereasTypeOf是一个库函数,它只返回其第一个参数,但要求它与第二个参数共享其类型。它在库中定义为:

asTypeOf :: t -> t -> t
asTypeOf x y = x

或者,我们可以利用 GHC Haskell 的一个非常常用的扩展。首先,我们需要通过添加来启用它

{-# LANGUAGE ScopedTypeVariables #-}

在模块文件的顶部。然后,我们可以简单地写

cyclicGenerators :: forall a . (FiniteGroup a) => [a]
                 -- ^^^^^^^^^^ added
cyclicGenerators = filter isGenerator set
        where isGenerator = (\x -> groupOrder (set :: [a]) == elemOrder x)

我们显式声明set了 type [a],所以它属于同一个组。

于 2016-01-30T21:28:29.623 回答