使用 class 中定义的函数

use the functions defined in the class

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

不幸的是,我的所有函数都需要标识元素、集合和操作。我想定义 class 的适当实例并使用它而不是这个三重奏。我的问题从这里开始,我不太知道如何去做,我在互联网上能找到的所有内容都只包含定义示例,没有使用示例。

最终我想和小组 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)]

并且它对函数 op 工作正常,例如:

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

很遗憾,我无法使用 identityset。如何使用?

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

例如我有这个:

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

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

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

I cant use the identity and set, how to use it?

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

set :: [Z2]
identity :: Z2

将它们传递给某些需要 Z2 的函数也可以。只要编译器能弄清楚你在谈论哪个有限群,你就没事了。否则,您将收到 "ambiguous ..." 错误。

How to replace signatures in function and again how to use identity and set in function which I've already defined.

例如尝试

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

上面的编译器"knows"那个set指的是有限群a,因为我们必须return一个[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)

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

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 属于 [a] 类型,因此它属于同一组。