使用类中定义的函数

时间:2016-01-30 21:07:00

标签: haskell functional-programming finite-group-theory

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

不幸的是我的所有功能都需要标识元素,设置和操作。我想定义类的适当实例并使用它而不是这个三重奏。这里开始我的问题,我不知道如何去做,我在互联网上找到的只包含定义的例子,没有用例。

最后,我想与小组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。我该如何使用它?

我也无法弄清楚如何重构现有函数以使用我的类型类。

例如我有这个:

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

它工作正常,但我希望有这样的东西:

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

1 个答案:

答案 0 :(得分:2)

  

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

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

set :: [Z2]
identity :: Z2

将它们传递给某个需要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不会更改输入列表的类型,因此{{ 1}}也必须是set类型。这里类型推断在传播类型时非常有效,因此选择了正确的有限群实例。

编辑:OP提出代码

[a]

会触发歧义错误。实际上,最后一个cyclicGenerators :: (FiniteGroup a) => [a] cyclicGenerators = filter isGenerator set where isGenerator = (\x -> groupOrder set == elemOrder x) 并不强制属于同一个组 - 将另一个组的组顺序与set的顺序进行比较是有意义的。例如。 x会输入check,因为两者都是整数。

因此,我们需要说明groupOrder (set :: [Z5]) == elemOrder (identity :: [Z2])的类型是set。简单的Haskell方式是

[a]

其中 where isGenerator = (\x -> groupOrder (set `asTypeOf` [x]) == elemOrder x) 是一个库函数,它只返回第一个参数,但要求它与第二个参数共享其类型。它在库中定义为:

asTypeOf

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

来启用它
asTypeOf :: t -> t -> t
asTypeOf x y = x

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

{-# LANGUAGE ScopedTypeVariables #-}

我们明确声明cyclicGenerators :: forall a . (FiniteGroup a) => [a] -- ^^^^^^^^^^ added cyclicGenerators = filter isGenerator set where isGenerator = (\x -> groupOrder (set :: [a]) == elemOrder x) 属于set类型,因此属于同一组。