使用 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
很遗憾,我无法使用 identity
和 set
。如何使用?
我也不知道如何重构现有函数以使用我的类型 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]
类型,因此它属于同一组。
我正在编写一个程序来表示有限群并对其元素进行简单操作。我编写了我需要的大部分功能,例如逆元素、生成器、检查子集是否为子组等。
不幸的是,我的所有函数都需要标识元素、集合和操作。我想定义 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
很遗憾,我无法使用 identity
和 set
。如何使用?
我也不知道如何重构现有函数以使用我的类型 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]
类型,因此它属于同一组。