【问题标题】:Declaring a field from algebra by class and / or by data?按类和/或数据从代数声明一个字段?
【发布时间】:2016-12-31 19:26:03
【问题描述】:

我想在 Haskell 中为 field 建模。字段是一组元素加上两个运算,可以看作是乘法和加法。我是这样处理的:

data Field a = Field [a] (a -> a -> a) (a -> a -> a)

elements :: Field a -> [a]
elements (Field els _ _) = els

add :: Field a -> a -> a -> a
add (Field _ addop _) = addop

mul :: Field a -> a -> a -> a
mul (Field _ _ mulop) = mulop

但是,我现在想对字段上的多项式进行建模,即类似

data Poly = Poly f [(a, Int)]

其中f 应该是一个字段,a 应该是该字段的类型。列表[(a, Int)] 将表示多项式,例如,

[(4, 2), (1, 1)] = 4 * x^2 + 1 * x^1

但我想不出如何在 Haskell 中实现这一点。我想也许我可以以某种方式将Field 声明为一个类,然后以某种方式将 Poly 限制为仅与 Fields 一起使用,但据我所知,我无法限制数据构造函数。

【问题讨论】:

  • data Poly a = Poly (Field a -> [ (Int, [a]) ])
  • 请参阅this answer,了解为什么我们不再对数据构造函数施加类约束。

标签: haskell algebra


【解决方案1】:

另一种方法是定义一个Field 类型类:

class Field a where
    rplus :: a -> a -> a
    rmult :: a -> a -> a
    rnegate :: a -> a
    rinverse :: a -> a
    runit :: a
    rzero :: a

对于每个字段,定义一个表示该字段基础集的类型,然后为该类型定义一个适当的实例。您有责任确保您的实现遵守各种场定律(乘法分布在加法之上,任何元素乘以它的倒数为 1,等等)。

请参阅最后一个示例,了解如何为字段上的多项式定义 Field 实例。

示例

整数模 7

-- Haskell doesn't have dependent types yet, so use the
-- next best thing: a smart constructor
newtype Z7 = Z7 Integer
makeZ7 :: Integer -> Z7
makeZ7 x = Z7 $ (x `mod` 7)

instance Field Z7 where
    rplus (Z7 a) (Z7 b) = makeZ7 (a + b)
    rmult (Z7 a) (Z7 b) = makeZ7 (a * b)
    rzero = makeZ7 0
    runit = makeZ7 1
    rnegate (Z7 a) = makeZ7 (7 - a)
    -- Necessarily partial, since 0 doesn't have an inverse
    rinverse (Z7 a) | a == 1 = makeZ7 1
                    | a == 2 = makeZ7 4
                    | a == 3 = makeZ7 5
                    | a == 4 = makeZ7 2
                    | a == 5 = makeZ7 3
                    | a == 6 = makeZ7 6

理性

这个比较简单,因为Integral a => Ratio a 已经是Num 的一个实例,所以我们可以免费获得大部分实现。

import Data.Ratio
instance Integeral a => Field (Ratio a) where
    rplus = (+)
    rmult = (*)
    rnegate = negate
    rinverse q = denominator q % numerator q
    rzero = 0
    runit = 1

域上的多项式

多项式的系数可以是任何你想要的。

data Poly f = Poly [(f, Int)]

但是,多项式仅在系数本身来自某个域时才形成一个域,因此您可以在此处声明该约束。

-- A type Poly f is a field if f is a field.
-- Fields: Poly Z7, Integral a => Poly (Ratio a)
-- Not a field: Poly Integer
instance Field f => Field (Poly f) where
    runit = Poly [(runit, 0)] -- Not Poly [(1,0)]
    rzero = Poly [(rzero, 0)] -- Not Poly [(0,0)]
    -- Not Poly [(-c, e) | (c,e) <- p]
    rnegate (Poly p) = Poly [(rnegate c, e) | (c,e) <- p]
    -- Left as an exercise for the reader
    -- Remember to use runit instead of 1, rzero instead of 0
    -- and rnegate instead of - where appropriate.
    rinverse p = ...
    rplus p q = ...
    rmult p q = ...

一些非常简单的示例不需要我完成Poly 实例的实现。 (您可以为所有涉及的类型派生Show。)

> runit :: Z7
Z7 1
> runit :: Rational  -- type Rational = Ratio Integer
1 % 1
> runit :: Poly Z7
Poly [(Z7 1,0)]
> runit :: Poly Rational
Poly [(1 % 1,0)]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多