Haskell 使用类中定义的函数

Haskell 使用类中定义的函数,haskell,functional-programming,finite-group-theory,Haskell,Functional Programming,Finite Group Theory,我正在写一个程序来表示有限群和对其元素的简单运算。我编写了我需要的大部分功能,例如逆元素、生成器、检查子集是否为子组等 不幸的是,我所有的函数都需要标识元素、集合和操作。我想定义类的适当实例,并使用它来代替这个三元组。我的问题就从这里开始,我不太知道该怎么做,我在互联网上能找到的只有定义的例子,没有用法的例子 最后,我想与组Sn,到目前为止,我已经在(Zn+)上测试了我的代码 我写道: data Z2 = Elm Int deriving (Show, Eq) z2 :: Int -> Z

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

不幸的是,我所有的函数都需要标识元素、集合和操作。我想定义类的适当实例,并使用它来代替这个三元组。我的问题就从这里开始,我不太知道该怎么做,我在互联网上能找到的只有定义的例子,没有用法的例子

最后,我想与组
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
不幸的是,我不能使用
identity
set
。我如何使用它

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

例如,我有:

cyclicGenerators :: (Eq a) => a -> [a] -> (a -> a -> a) -> [a]
它工作得很好,但我想要这样的东西:

cyclicGenerators :: (Eq a) => FiniteGroup a -> [a]
我不能使用身份和设置,如何使用它

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

set :: [Z2]
identity :: Z2
将它们传递给需要
Z2
的函数也可以。只要编译器能找出你所说的是哪一个有限群,你就没事了。否则,将出现“不明确…”错误

如何在函数中替换签名,以及如何在我已经定义的函数中使用identity和set

试试看

cyclicGenerators :: (Eq a, FiniteGroup a) => [a]
cyclicGenerators = filter isGenerator set
  where isGenerator x = ...  -- a Boolean telling whether it's a generator
上面,编译器“知道”集合
指的是有限群
a
,因为我们必须返回
[a]
,并且
过滤器
不会改变输入列表的类型,因此集合
也必须是
[a]
类型。在这里,类型推断在传播类型时非常有效,因此可以选择正确的有限群实例


编辑:OP提出代码

cyclicGenerators :: (FiniteGroup a) => [a]
cyclicGenerators = filter isGenerator set
        where isGenerator = (\x -> groupOrder set == elemOrder x)
这会引发歧义错误。事实上,最后一个
集合
并不强制属于同一组——将另一组的组顺序与
x
的顺序进行比较是有意义的。例如,
groupOrder(set:[Z5])==elemOrder(identity:[Z2])
将进行类型检查,因为两者都是整数

所以我们需要声明
集合的类型是
[a]
。简单的哈斯克尔方法是

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

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

我写了这样的话:得到了:谢谢,你帮了我很多忙!有没有一个地方可以让我更多地了解类似的问题?你能告诉我“全部a”是什么意思吗?基本上,全部a的通用量词
表示调用方可以选择
a
作为它想要的内容。请注意,在这种特殊情况下,省略所有a的
不会更改类型:调用方无论如何都可以选择
a
。然而,GHC处理这个多余的量词的意思是“注意调用方选择的
a
——如果下面我再次使用
a
,我指的是这样选择的类型,因为你可以阅读到血淋淋的细节